]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
a2facf579acf1361bcfd7fc41df6484bc1082f8a
[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.4';
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 = 'object' == 'object' && exports && !exports.nodeType && exports;
447
448   /** Detect free variable `module`. */
449   var freeModule = freeExports && 'object' == '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 and iteratees accept only
1591      * one argument. The heuristic for whether a section qualifies for shortcut
1592      * 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) as well as ES2015 template strings. Change the
1752      * following template settings to use 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 || (!isRight && arrLength == length && takeCount == length)) {
1900         return baseWrapperValue(array, this.__actions__);
1901       }
1902       var result = [];
1903
1904       outer:
1905       while (length-- && resIndex < takeCount) {
1906         index += dir;
1907
1908         var iterIndex = -1,
1909             value = array[index];
1910
1911         while (++iterIndex < iterLength) {
1912           var data = iteratees[iterIndex],
1913               iteratee = data.iteratee,
1914               type = data.type,
1915               computed = iteratee(value);
1916
1917           if (type == LAZY_MAP_FLAG) {
1918             value = computed;
1919           } else if (!computed) {
1920             if (type == LAZY_FILTER_FLAG) {
1921               continue outer;
1922             } else {
1923               break outer;
1924             }
1925           }
1926         }
1927         result[resIndex++] = value;
1928       }
1929       return result;
1930     }
1931
1932     // Ensure `LazyWrapper` is an instance of `baseLodash`.
1933     LazyWrapper.prototype = baseCreate(baseLodash.prototype);
1934     LazyWrapper.prototype.constructor = LazyWrapper;
1935
1936     /*------------------------------------------------------------------------*/
1937
1938     /**
1939      * Creates a hash object.
1940      *
1941      * @private
1942      * @constructor
1943      * @param {Array} [entries] The key-value pairs to cache.
1944      */
1945     function Hash(entries) {
1946       var index = -1,
1947           length = entries == null ? 0 : entries.length;
1948
1949       this.clear();
1950       while (++index < length) {
1951         var entry = entries[index];
1952         this.set(entry[0], entry[1]);
1953       }
1954     }
1955
1956     /**
1957      * Removes all key-value entries from the hash.
1958      *
1959      * @private
1960      * @name clear
1961      * @memberOf Hash
1962      */
1963     function hashClear() {
1964       this.__data__ = nativeCreate ? nativeCreate(null) : {};
1965       this.size = 0;
1966     }
1967
1968     /**
1969      * Removes `key` and its value from the hash.
1970      *
1971      * @private
1972      * @name delete
1973      * @memberOf Hash
1974      * @param {Object} hash The hash to modify.
1975      * @param {string} key The key of the value to remove.
1976      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
1977      */
1978     function hashDelete(key) {
1979       var result = this.has(key) && delete this.__data__[key];
1980       this.size -= result ? 1 : 0;
1981       return result;
1982     }
1983
1984     /**
1985      * Gets the hash value for `key`.
1986      *
1987      * @private
1988      * @name get
1989      * @memberOf Hash
1990      * @param {string} key The key of the value to get.
1991      * @returns {*} Returns the entry value.
1992      */
1993     function hashGet(key) {
1994       var data = this.__data__;
1995       if (nativeCreate) {
1996         var result = data[key];
1997         return result === HASH_UNDEFINED ? undefined : result;
1998       }
1999       return hasOwnProperty.call(data, key) ? data[key] : undefined;
2000     }
2001
2002     /**
2003      * Checks if a hash value for `key` exists.
2004      *
2005      * @private
2006      * @name has
2007      * @memberOf Hash
2008      * @param {string} key The key of the entry to check.
2009      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2010      */
2011     function hashHas(key) {
2012       var data = this.__data__;
2013       return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
2014     }
2015
2016     /**
2017      * Sets the hash `key` to `value`.
2018      *
2019      * @private
2020      * @name set
2021      * @memberOf Hash
2022      * @param {string} key The key of the value to set.
2023      * @param {*} value The value to set.
2024      * @returns {Object} Returns the hash instance.
2025      */
2026     function hashSet(key, value) {
2027       var data = this.__data__;
2028       this.size += this.has(key) ? 0 : 1;
2029       data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
2030       return this;
2031     }
2032
2033     // Add methods to `Hash`.
2034     Hash.prototype.clear = hashClear;
2035     Hash.prototype['delete'] = hashDelete;
2036     Hash.prototype.get = hashGet;
2037     Hash.prototype.has = hashHas;
2038     Hash.prototype.set = hashSet;
2039
2040     /*------------------------------------------------------------------------*/
2041
2042     /**
2043      * Creates an list cache object.
2044      *
2045      * @private
2046      * @constructor
2047      * @param {Array} [entries] The key-value pairs to cache.
2048      */
2049     function ListCache(entries) {
2050       var index = -1,
2051           length = entries == null ? 0 : entries.length;
2052
2053       this.clear();
2054       while (++index < length) {
2055         var entry = entries[index];
2056         this.set(entry[0], entry[1]);
2057       }
2058     }
2059
2060     /**
2061      * Removes all key-value entries from the list cache.
2062      *
2063      * @private
2064      * @name clear
2065      * @memberOf ListCache
2066      */
2067     function listCacheClear() {
2068       this.__data__ = [];
2069       this.size = 0;
2070     }
2071
2072     /**
2073      * Removes `key` and its value from the list cache.
2074      *
2075      * @private
2076      * @name delete
2077      * @memberOf ListCache
2078      * @param {string} key The key of the value to remove.
2079      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2080      */
2081     function listCacheDelete(key) {
2082       var data = this.__data__,
2083           index = assocIndexOf(data, key);
2084
2085       if (index < 0) {
2086         return false;
2087       }
2088       var lastIndex = data.length - 1;
2089       if (index == lastIndex) {
2090         data.pop();
2091       } else {
2092         splice.call(data, index, 1);
2093       }
2094       --this.size;
2095       return true;
2096     }
2097
2098     /**
2099      * Gets the list cache value for `key`.
2100      *
2101      * @private
2102      * @name get
2103      * @memberOf ListCache
2104      * @param {string} key The key of the value to get.
2105      * @returns {*} Returns the entry value.
2106      */
2107     function listCacheGet(key) {
2108       var data = this.__data__,
2109           index = assocIndexOf(data, key);
2110
2111       return index < 0 ? undefined : data[index][1];
2112     }
2113
2114     /**
2115      * Checks if a list cache value for `key` exists.
2116      *
2117      * @private
2118      * @name has
2119      * @memberOf ListCache
2120      * @param {string} key The key of the entry to check.
2121      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2122      */
2123     function listCacheHas(key) {
2124       return assocIndexOf(this.__data__, key) > -1;
2125     }
2126
2127     /**
2128      * Sets the list cache `key` to `value`.
2129      *
2130      * @private
2131      * @name set
2132      * @memberOf ListCache
2133      * @param {string} key The key of the value to set.
2134      * @param {*} value The value to set.
2135      * @returns {Object} Returns the list cache instance.
2136      */
2137     function listCacheSet(key, value) {
2138       var data = this.__data__,
2139           index = assocIndexOf(data, key);
2140
2141       if (index < 0) {
2142         ++this.size;
2143         data.push([key, value]);
2144       } else {
2145         data[index][1] = value;
2146       }
2147       return this;
2148     }
2149
2150     // Add methods to `ListCache`.
2151     ListCache.prototype.clear = listCacheClear;
2152     ListCache.prototype['delete'] = listCacheDelete;
2153     ListCache.prototype.get = listCacheGet;
2154     ListCache.prototype.has = listCacheHas;
2155     ListCache.prototype.set = listCacheSet;
2156
2157     /*------------------------------------------------------------------------*/
2158
2159     /**
2160      * Creates a map cache object to store key-value pairs.
2161      *
2162      * @private
2163      * @constructor
2164      * @param {Array} [entries] The key-value pairs to cache.
2165      */
2166     function MapCache(entries) {
2167       var index = -1,
2168           length = entries == null ? 0 : entries.length;
2169
2170       this.clear();
2171       while (++index < length) {
2172         var entry = entries[index];
2173         this.set(entry[0], entry[1]);
2174       }
2175     }
2176
2177     /**
2178      * Removes all key-value entries from the map.
2179      *
2180      * @private
2181      * @name clear
2182      * @memberOf MapCache
2183      */
2184     function mapCacheClear() {
2185       this.size = 0;
2186       this.__data__ = {
2187         'hash': new Hash,
2188         'map': new (Map || ListCache),
2189         'string': new Hash
2190       };
2191     }
2192
2193     /**
2194      * Removes `key` and its value from the map.
2195      *
2196      * @private
2197      * @name delete
2198      * @memberOf MapCache
2199      * @param {string} key The key of the value to remove.
2200      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2201      */
2202     function mapCacheDelete(key) {
2203       var result = getMapData(this, key)['delete'](key);
2204       this.size -= result ? 1 : 0;
2205       return result;
2206     }
2207
2208     /**
2209      * Gets the map value for `key`.
2210      *
2211      * @private
2212      * @name get
2213      * @memberOf MapCache
2214      * @param {string} key The key of the value to get.
2215      * @returns {*} Returns the entry value.
2216      */
2217     function mapCacheGet(key) {
2218       return getMapData(this, key).get(key);
2219     }
2220
2221     /**
2222      * Checks if a map value for `key` exists.
2223      *
2224      * @private
2225      * @name has
2226      * @memberOf MapCache
2227      * @param {string} key The key of the entry to check.
2228      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2229      */
2230     function mapCacheHas(key) {
2231       return getMapData(this, key).has(key);
2232     }
2233
2234     /**
2235      * Sets the map `key` to `value`.
2236      *
2237      * @private
2238      * @name set
2239      * @memberOf MapCache
2240      * @param {string} key The key of the value to set.
2241      * @param {*} value The value to set.
2242      * @returns {Object} Returns the map cache instance.
2243      */
2244     function mapCacheSet(key, value) {
2245       var data = getMapData(this, key),
2246           size = data.size;
2247
2248       data.set(key, value);
2249       this.size += data.size == size ? 0 : 1;
2250       return this;
2251     }
2252
2253     // Add methods to `MapCache`.
2254     MapCache.prototype.clear = mapCacheClear;
2255     MapCache.prototype['delete'] = mapCacheDelete;
2256     MapCache.prototype.get = mapCacheGet;
2257     MapCache.prototype.has = mapCacheHas;
2258     MapCache.prototype.set = mapCacheSet;
2259
2260     /*------------------------------------------------------------------------*/
2261
2262     /**
2263      *
2264      * Creates an array cache object to store unique values.
2265      *
2266      * @private
2267      * @constructor
2268      * @param {Array} [values] The values to cache.
2269      */
2270     function SetCache(values) {
2271       var index = -1,
2272           length = values == null ? 0 : values.length;
2273
2274       this.__data__ = new MapCache;
2275       while (++index < length) {
2276         this.add(values[index]);
2277       }
2278     }
2279
2280     /**
2281      * Adds `value` to the array cache.
2282      *
2283      * @private
2284      * @name add
2285      * @memberOf SetCache
2286      * @alias push
2287      * @param {*} value The value to cache.
2288      * @returns {Object} Returns the cache instance.
2289      */
2290     function setCacheAdd(value) {
2291       this.__data__.set(value, HASH_UNDEFINED);
2292       return this;
2293     }
2294
2295     /**
2296      * Checks if `value` is in the array cache.
2297      *
2298      * @private
2299      * @name has
2300      * @memberOf SetCache
2301      * @param {*} value The value to search for.
2302      * @returns {number} Returns `true` if `value` is found, else `false`.
2303      */
2304     function setCacheHas(value) {
2305       return this.__data__.has(value);
2306     }
2307
2308     // Add methods to `SetCache`.
2309     SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
2310     SetCache.prototype.has = setCacheHas;
2311
2312     /*------------------------------------------------------------------------*/
2313
2314     /**
2315      * Creates a stack cache object to store key-value pairs.
2316      *
2317      * @private
2318      * @constructor
2319      * @param {Array} [entries] The key-value pairs to cache.
2320      */
2321     function Stack(entries) {
2322       var data = this.__data__ = new ListCache(entries);
2323       this.size = data.size;
2324     }
2325
2326     /**
2327      * Removes all key-value entries from the stack.
2328      *
2329      * @private
2330      * @name clear
2331      * @memberOf Stack
2332      */
2333     function stackClear() {
2334       this.__data__ = new ListCache;
2335       this.size = 0;
2336     }
2337
2338     /**
2339      * Removes `key` and its value from the stack.
2340      *
2341      * @private
2342      * @name delete
2343      * @memberOf Stack
2344      * @param {string} key The key of the value to remove.
2345      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2346      */
2347     function stackDelete(key) {
2348       var data = this.__data__,
2349           result = data['delete'](key);
2350
2351       this.size = data.size;
2352       return result;
2353     }
2354
2355     /**
2356      * Gets the stack value for `key`.
2357      *
2358      * @private
2359      * @name get
2360      * @memberOf Stack
2361      * @param {string} key The key of the value to get.
2362      * @returns {*} Returns the entry value.
2363      */
2364     function stackGet(key) {
2365       return this.__data__.get(key);
2366     }
2367
2368     /**
2369      * Checks if a stack value for `key` exists.
2370      *
2371      * @private
2372      * @name has
2373      * @memberOf Stack
2374      * @param {string} key The key of the entry to check.
2375      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2376      */
2377     function stackHas(key) {
2378       return this.__data__.has(key);
2379     }
2380
2381     /**
2382      * Sets the stack `key` to `value`.
2383      *
2384      * @private
2385      * @name set
2386      * @memberOf Stack
2387      * @param {string} key The key of the value to set.
2388      * @param {*} value The value to set.
2389      * @returns {Object} Returns the stack cache instance.
2390      */
2391     function stackSet(key, value) {
2392       var data = this.__data__;
2393       if (data instanceof ListCache) {
2394         var pairs = data.__data__;
2395         if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2396           pairs.push([key, value]);
2397           this.size = ++data.size;
2398           return this;
2399         }
2400         data = this.__data__ = new MapCache(pairs);
2401       }
2402       data.set(key, value);
2403       this.size = data.size;
2404       return this;
2405     }
2406
2407     // Add methods to `Stack`.
2408     Stack.prototype.clear = stackClear;
2409     Stack.prototype['delete'] = stackDelete;
2410     Stack.prototype.get = stackGet;
2411     Stack.prototype.has = stackHas;
2412     Stack.prototype.set = stackSet;
2413
2414     /*------------------------------------------------------------------------*/
2415
2416     /**
2417      * Creates an array of the enumerable property names of the array-like `value`.
2418      *
2419      * @private
2420      * @param {*} value The value to query.
2421      * @param {boolean} inherited Specify returning inherited property names.
2422      * @returns {Array} Returns the array of property names.
2423      */
2424     function arrayLikeKeys(value, inherited) {
2425       var isArr = isArray(value),
2426           isArg = !isArr && isArguments(value),
2427           isBuff = !isArr && !isArg && isBuffer(value),
2428           isType = !isArr && !isArg && !isBuff && isTypedArray(value),
2429           skipIndexes = isArr || isArg || isBuff || isType,
2430           result = skipIndexes ? baseTimes(value.length, String) : [],
2431           length = result.length;
2432
2433       for (var key in value) {
2434         if ((inherited || hasOwnProperty.call(value, key)) &&
2435             !(skipIndexes && (
2436                // Safari 9 has enumerable `arguments.length` in strict mode.
2437                key == 'length' ||
2438                // Node.js 0.10 has enumerable non-index properties on buffers.
2439                (isBuff && (key == 'offset' || key == 'parent')) ||
2440                // PhantomJS 2 has enumerable non-index properties on typed arrays.
2441                (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
2442                // Skip index properties.
2443                isIndex(key, length)
2444             ))) {
2445           result.push(key);
2446         }
2447       }
2448       return result;
2449     }
2450
2451     /**
2452      * A specialized version of `_.sample` for arrays.
2453      *
2454      * @private
2455      * @param {Array} array The array to sample.
2456      * @returns {*} Returns the random element.
2457      */
2458     function arraySample(array) {
2459       var length = array.length;
2460       return length ? array[baseRandom(0, length - 1)] : undefined;
2461     }
2462
2463     /**
2464      * A specialized version of `_.sampleSize` for arrays.
2465      *
2466      * @private
2467      * @param {Array} array The array to sample.
2468      * @param {number} n The number of elements to sample.
2469      * @returns {Array} Returns the random elements.
2470      */
2471     function arraySampleSize(array, n) {
2472       return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
2473     }
2474
2475     /**
2476      * A specialized version of `_.shuffle` for arrays.
2477      *
2478      * @private
2479      * @param {Array} array The array to shuffle.
2480      * @returns {Array} Returns the new shuffled array.
2481      */
2482     function arrayShuffle(array) {
2483       return shuffleSelf(copyArray(array));
2484     }
2485
2486     /**
2487      * This function is like `assignValue` except that it doesn't assign
2488      * `undefined` values.
2489      *
2490      * @private
2491      * @param {Object} object The object to modify.
2492      * @param {string} key The key of the property to assign.
2493      * @param {*} value The value to assign.
2494      */
2495     function assignMergeValue(object, key, value) {
2496       if ((value !== undefined && !eq(object[key], value)) ||
2497           (value === undefined && !(key in object))) {
2498         baseAssignValue(object, key, value);
2499       }
2500     }
2501
2502     /**
2503      * Assigns `value` to `key` of `object` if the existing value is not equivalent
2504      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
2505      * for equality comparisons.
2506      *
2507      * @private
2508      * @param {Object} object The object to modify.
2509      * @param {string} key The key of the property to assign.
2510      * @param {*} value The value to assign.
2511      */
2512     function assignValue(object, key, value) {
2513       var objValue = object[key];
2514       if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
2515           (value === undefined && !(key in object))) {
2516         baseAssignValue(object, key, value);
2517       }
2518     }
2519
2520     /**
2521      * Gets the index at which the `key` is found in `array` of key-value pairs.
2522      *
2523      * @private
2524      * @param {Array} array The array to inspect.
2525      * @param {*} key The key to search for.
2526      * @returns {number} Returns the index of the matched value, else `-1`.
2527      */
2528     function assocIndexOf(array, key) {
2529       var length = array.length;
2530       while (length--) {
2531         if (eq(array[length][0], key)) {
2532           return length;
2533         }
2534       }
2535       return -1;
2536     }
2537
2538     /**
2539      * Aggregates elements of `collection` on `accumulator` with keys transformed
2540      * by `iteratee` and values set by `setter`.
2541      *
2542      * @private
2543      * @param {Array|Object} collection The collection to iterate over.
2544      * @param {Function} setter The function to set `accumulator` values.
2545      * @param {Function} iteratee The iteratee to transform keys.
2546      * @param {Object} accumulator The initial aggregated object.
2547      * @returns {Function} Returns `accumulator`.
2548      */
2549     function baseAggregator(collection, setter, iteratee, accumulator) {
2550       baseEach(collection, function(value, key, collection) {
2551         setter(accumulator, value, iteratee(value), collection);
2552       });
2553       return accumulator;
2554     }
2555
2556     /**
2557      * The base implementation of `_.assign` without support for multiple sources
2558      * or `customizer` functions.
2559      *
2560      * @private
2561      * @param {Object} object The destination object.
2562      * @param {Object} source The source object.
2563      * @returns {Object} Returns `object`.
2564      */
2565     function baseAssign(object, source) {
2566       return object && copyObject(source, keys(source), object);
2567     }
2568
2569     /**
2570      * The base implementation of `_.assignIn` without support for multiple sources
2571      * or `customizer` functions.
2572      *
2573      * @private
2574      * @param {Object} object The destination object.
2575      * @param {Object} source The source object.
2576      * @returns {Object} Returns `object`.
2577      */
2578     function baseAssignIn(object, source) {
2579       return object && copyObject(source, keysIn(source), object);
2580     }
2581
2582     /**
2583      * The base implementation of `assignValue` and `assignMergeValue` without
2584      * value checks.
2585      *
2586      * @private
2587      * @param {Object} object The object to modify.
2588      * @param {string} key The key of the property to assign.
2589      * @param {*} value The value to assign.
2590      */
2591     function baseAssignValue(object, key, value) {
2592       if (key == '__proto__' && defineProperty) {
2593         defineProperty(object, key, {
2594           'configurable': true,
2595           'enumerable': true,
2596           'value': value,
2597           'writable': true
2598         });
2599       } else {
2600         object[key] = value;
2601       }
2602     }
2603
2604     /**
2605      * The base implementation of `_.at` without support for individual paths.
2606      *
2607      * @private
2608      * @param {Object} object The object to iterate over.
2609      * @param {string[]} paths The property paths to pick.
2610      * @returns {Array} Returns the picked elements.
2611      */
2612     function baseAt(object, paths) {
2613       var index = -1,
2614           length = paths.length,
2615           result = Array(length),
2616           skip = object == null;
2617
2618       while (++index < length) {
2619         result[index] = skip ? undefined : get(object, paths[index]);
2620       }
2621       return result;
2622     }
2623
2624     /**
2625      * The base implementation of `_.clamp` which doesn't coerce arguments.
2626      *
2627      * @private
2628      * @param {number} number The number to clamp.
2629      * @param {number} [lower] The lower bound.
2630      * @param {number} upper The upper bound.
2631      * @returns {number} Returns the clamped number.
2632      */
2633     function baseClamp(number, lower, upper) {
2634       if (number === number) {
2635         if (upper !== undefined) {
2636           number = number <= upper ? number : upper;
2637         }
2638         if (lower !== undefined) {
2639           number = number >= lower ? number : lower;
2640         }
2641       }
2642       return number;
2643     }
2644
2645     /**
2646      * The base implementation of `_.clone` and `_.cloneDeep` which tracks
2647      * traversed objects.
2648      *
2649      * @private
2650      * @param {*} value The value to clone.
2651      * @param {boolean} bitmask The bitmask flags.
2652      *  1 - Deep clone
2653      *  2 - Flatten inherited properties
2654      *  4 - Clone symbols
2655      * @param {Function} [customizer] The function to customize cloning.
2656      * @param {string} [key] The key of `value`.
2657      * @param {Object} [object] The parent object of `value`.
2658      * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
2659      * @returns {*} Returns the cloned value.
2660      */
2661     function baseClone(value, bitmask, customizer, key, object, stack) {
2662       var result,
2663           isDeep = bitmask & CLONE_DEEP_FLAG,
2664           isFlat = bitmask & CLONE_FLAT_FLAG,
2665           isFull = bitmask & CLONE_SYMBOLS_FLAG;
2666
2667       if (customizer) {
2668         result = object ? customizer(value, key, object, stack) : customizer(value);
2669       }
2670       if (result !== undefined) {
2671         return result;
2672       }
2673       if (!isObject(value)) {
2674         return value;
2675       }
2676       var isArr = isArray(value);
2677       if (isArr) {
2678         result = initCloneArray(value);
2679         if (!isDeep) {
2680           return copyArray(value, result);
2681         }
2682       } else {
2683         var tag = getTag(value),
2684             isFunc = tag == funcTag || tag == genTag;
2685
2686         if (isBuffer(value)) {
2687           return cloneBuffer(value, isDeep);
2688         }
2689         if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
2690           result = (isFlat || isFunc) ? {} : initCloneObject(value);
2691           if (!isDeep) {
2692             return isFlat
2693               ? copySymbolsIn(value, baseAssignIn(result, value))
2694               : copySymbols(value, baseAssign(result, value));
2695           }
2696         } else {
2697           if (!cloneableTags[tag]) {
2698             return object ? value : {};
2699           }
2700           result = initCloneByTag(value, tag, baseClone, isDeep);
2701         }
2702       }
2703       // Check for circular references and return its corresponding clone.
2704       stack || (stack = new Stack);
2705       var stacked = stack.get(value);
2706       if (stacked) {
2707         return stacked;
2708       }
2709       stack.set(value, result);
2710
2711       var keysFunc = isFull
2712         ? (isFlat ? getAllKeysIn : getAllKeys)
2713         : (isFlat ? keysIn : keys);
2714
2715       var props = isArr ? undefined : keysFunc(value);
2716       arrayEach(props || value, function(subValue, key) {
2717         if (props) {
2718           key = subValue;
2719           subValue = value[key];
2720         }
2721         // Recursively populate clone (susceptible to call stack limits).
2722         assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
2723       });
2724       return result;
2725     }
2726
2727     /**
2728      * The base implementation of `_.conforms` which doesn't clone `source`.
2729      *
2730      * @private
2731      * @param {Object} source The object of property predicates to conform to.
2732      * @returns {Function} Returns the new spec function.
2733      */
2734     function baseConforms(source) {
2735       var props = keys(source);
2736       return function(object) {
2737         return baseConformsTo(object, source, props);
2738       };
2739     }
2740
2741     /**
2742      * The base implementation of `_.conformsTo` which accepts `props` to check.
2743      *
2744      * @private
2745      * @param {Object} object The object to inspect.
2746      * @param {Object} source The object of property predicates to conform to.
2747      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
2748      */
2749     function baseConformsTo(object, source, props) {
2750       var length = props.length;
2751       if (object == null) {
2752         return !length;
2753       }
2754       object = Object(object);
2755       while (length--) {
2756         var key = props[length],
2757             predicate = source[key],
2758             value = object[key];
2759
2760         if ((value === undefined && !(key in object)) || !predicate(value)) {
2761           return false;
2762         }
2763       }
2764       return true;
2765     }
2766
2767     /**
2768      * The base implementation of `_.delay` and `_.defer` which accepts `args`
2769      * to provide to `func`.
2770      *
2771      * @private
2772      * @param {Function} func The function to delay.
2773      * @param {number} wait The number of milliseconds to delay invocation.
2774      * @param {Array} args The arguments to provide to `func`.
2775      * @returns {number|Object} Returns the timer id or timeout object.
2776      */
2777     function baseDelay(func, wait, args) {
2778       if (typeof func != 'function') {
2779         throw new TypeError(FUNC_ERROR_TEXT);
2780       }
2781       return setTimeout(function() { func.apply(undefined, args); }, wait);
2782     }
2783
2784     /**
2785      * The base implementation of methods like `_.difference` without support
2786      * for excluding multiple arrays or iteratee shorthands.
2787      *
2788      * @private
2789      * @param {Array} array The array to inspect.
2790      * @param {Array} values The values to exclude.
2791      * @param {Function} [iteratee] The iteratee invoked per element.
2792      * @param {Function} [comparator] The comparator invoked per element.
2793      * @returns {Array} Returns the new array of filtered values.
2794      */
2795     function baseDifference(array, values, iteratee, comparator) {
2796       var index = -1,
2797           includes = arrayIncludes,
2798           isCommon = true,
2799           length = array.length,
2800           result = [],
2801           valuesLength = values.length;
2802
2803       if (!length) {
2804         return result;
2805       }
2806       if (iteratee) {
2807         values = arrayMap(values, baseUnary(iteratee));
2808       }
2809       if (comparator) {
2810         includes = arrayIncludesWith;
2811         isCommon = false;
2812       }
2813       else if (values.length >= LARGE_ARRAY_SIZE) {
2814         includes = cacheHas;
2815         isCommon = false;
2816         values = new SetCache(values);
2817       }
2818       outer:
2819       while (++index < length) {
2820         var value = array[index],
2821             computed = iteratee == null ? value : iteratee(value);
2822
2823         value = (comparator || value !== 0) ? value : 0;
2824         if (isCommon && computed === computed) {
2825           var valuesIndex = valuesLength;
2826           while (valuesIndex--) {
2827             if (values[valuesIndex] === computed) {
2828               continue outer;
2829             }
2830           }
2831           result.push(value);
2832         }
2833         else if (!includes(values, computed, comparator)) {
2834           result.push(value);
2835         }
2836       }
2837       return result;
2838     }
2839
2840     /**
2841      * The base implementation of `_.forEach` without support for iteratee shorthands.
2842      *
2843      * @private
2844      * @param {Array|Object} collection The collection to iterate over.
2845      * @param {Function} iteratee The function invoked per iteration.
2846      * @returns {Array|Object} Returns `collection`.
2847      */
2848     var baseEach = createBaseEach(baseForOwn);
2849
2850     /**
2851      * The base implementation of `_.forEachRight` without support for iteratee shorthands.
2852      *
2853      * @private
2854      * @param {Array|Object} collection The collection to iterate over.
2855      * @param {Function} iteratee The function invoked per iteration.
2856      * @returns {Array|Object} Returns `collection`.
2857      */
2858     var baseEachRight = createBaseEach(baseForOwnRight, true);
2859
2860     /**
2861      * The base implementation of `_.every` without support for iteratee shorthands.
2862      *
2863      * @private
2864      * @param {Array|Object} collection The collection to iterate over.
2865      * @param {Function} predicate The function invoked per iteration.
2866      * @returns {boolean} Returns `true` if all elements pass the predicate check,
2867      *  else `false`
2868      */
2869     function baseEvery(collection, predicate) {
2870       var result = true;
2871       baseEach(collection, function(value, index, collection) {
2872         result = !!predicate(value, index, collection);
2873         return result;
2874       });
2875       return result;
2876     }
2877
2878     /**
2879      * The base implementation of methods like `_.max` and `_.min` which accepts a
2880      * `comparator` to determine the extremum value.
2881      *
2882      * @private
2883      * @param {Array} array The array to iterate over.
2884      * @param {Function} iteratee The iteratee invoked per iteration.
2885      * @param {Function} comparator The comparator used to compare values.
2886      * @returns {*} Returns the extremum value.
2887      */
2888     function baseExtremum(array, iteratee, comparator) {
2889       var index = -1,
2890           length = array.length;
2891
2892       while (++index < length) {
2893         var value = array[index],
2894             current = iteratee(value);
2895
2896         if (current != null && (computed === undefined
2897               ? (current === current && !isSymbol(current))
2898               : comparator(current, computed)
2899             )) {
2900           var computed = current,
2901               result = value;
2902         }
2903       }
2904       return result;
2905     }
2906
2907     /**
2908      * The base implementation of `_.fill` without an iteratee call guard.
2909      *
2910      * @private
2911      * @param {Array} array The array to fill.
2912      * @param {*} value The value to fill `array` with.
2913      * @param {number} [start=0] The start position.
2914      * @param {number} [end=array.length] The end position.
2915      * @returns {Array} Returns `array`.
2916      */
2917     function baseFill(array, value, start, end) {
2918       var length = array.length;
2919
2920       start = toInteger(start);
2921       if (start < 0) {
2922         start = -start > length ? 0 : (length + start);
2923       }
2924       end = (end === undefined || end > length) ? length : toInteger(end);
2925       if (end < 0) {
2926         end += length;
2927       }
2928       end = start > end ? 0 : toLength(end);
2929       while (start < end) {
2930         array[start++] = value;
2931       }
2932       return array;
2933     }
2934
2935     /**
2936      * The base implementation of `_.filter` without support for iteratee shorthands.
2937      *
2938      * @private
2939      * @param {Array|Object} collection The collection to iterate over.
2940      * @param {Function} predicate The function invoked per iteration.
2941      * @returns {Array} Returns the new filtered array.
2942      */
2943     function baseFilter(collection, predicate) {
2944       var result = [];
2945       baseEach(collection, function(value, index, collection) {
2946         if (predicate(value, index, collection)) {
2947           result.push(value);
2948         }
2949       });
2950       return result;
2951     }
2952
2953     /**
2954      * The base implementation of `_.flatten` with support for restricting flattening.
2955      *
2956      * @private
2957      * @param {Array} array The array to flatten.
2958      * @param {number} depth The maximum recursion depth.
2959      * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
2960      * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
2961      * @param {Array} [result=[]] The initial result value.
2962      * @returns {Array} Returns the new flattened array.
2963      */
2964     function baseFlatten(array, depth, predicate, isStrict, result) {
2965       var index = -1,
2966           length = array.length;
2967
2968       predicate || (predicate = isFlattenable);
2969       result || (result = []);
2970
2971       while (++index < length) {
2972         var value = array[index];
2973         if (depth > 0 && predicate(value)) {
2974           if (depth > 1) {
2975             // Recursively flatten arrays (susceptible to call stack limits).
2976             baseFlatten(value, depth - 1, predicate, isStrict, result);
2977           } else {
2978             arrayPush(result, value);
2979           }
2980         } else if (!isStrict) {
2981           result[result.length] = value;
2982         }
2983       }
2984       return result;
2985     }
2986
2987     /**
2988      * The base implementation of `baseForOwn` which iterates over `object`
2989      * properties returned by `keysFunc` and invokes `iteratee` for each property.
2990      * Iteratee functions may exit iteration early by explicitly returning `false`.
2991      *
2992      * @private
2993      * @param {Object} object The object to iterate over.
2994      * @param {Function} iteratee The function invoked per iteration.
2995      * @param {Function} keysFunc The function to get the keys of `object`.
2996      * @returns {Object} Returns `object`.
2997      */
2998     var baseFor = createBaseFor();
2999
3000     /**
3001      * This function is like `baseFor` except that it iterates over properties
3002      * in the opposite order.
3003      *
3004      * @private
3005      * @param {Object} object The object to iterate over.
3006      * @param {Function} iteratee The function invoked per iteration.
3007      * @param {Function} keysFunc The function to get the keys of `object`.
3008      * @returns {Object} Returns `object`.
3009      */
3010     var baseForRight = createBaseFor(true);
3011
3012     /**
3013      * The base implementation of `_.forOwn` without support for iteratee shorthands.
3014      *
3015      * @private
3016      * @param {Object} object The object to iterate over.
3017      * @param {Function} iteratee The function invoked per iteration.
3018      * @returns {Object} Returns `object`.
3019      */
3020     function baseForOwn(object, iteratee) {
3021       return object && baseFor(object, iteratee, keys);
3022     }
3023
3024     /**
3025      * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
3026      *
3027      * @private
3028      * @param {Object} object The object to iterate over.
3029      * @param {Function} iteratee The function invoked per iteration.
3030      * @returns {Object} Returns `object`.
3031      */
3032     function baseForOwnRight(object, iteratee) {
3033       return object && baseForRight(object, iteratee, keys);
3034     }
3035
3036     /**
3037      * The base implementation of `_.functions` which creates an array of
3038      * `object` function property names filtered from `props`.
3039      *
3040      * @private
3041      * @param {Object} object The object to inspect.
3042      * @param {Array} props The property names to filter.
3043      * @returns {Array} Returns the function names.
3044      */
3045     function baseFunctions(object, props) {
3046       return arrayFilter(props, function(key) {
3047         return isFunction(object[key]);
3048       });
3049     }
3050
3051     /**
3052      * The base implementation of `_.get` without support for default values.
3053      *
3054      * @private
3055      * @param {Object} object The object to query.
3056      * @param {Array|string} path The path of the property to get.
3057      * @returns {*} Returns the resolved value.
3058      */
3059     function baseGet(object, path) {
3060       path = castPath(path, object);
3061
3062       var index = 0,
3063           length = path.length;
3064
3065       while (object != null && index < length) {
3066         object = object[toKey(path[index++])];
3067       }
3068       return (index && index == length) ? object : undefined;
3069     }
3070
3071     /**
3072      * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
3073      * `keysFunc` and `symbolsFunc` to get the enumerable property names and
3074      * symbols of `object`.
3075      *
3076      * @private
3077      * @param {Object} object The object to query.
3078      * @param {Function} keysFunc The function to get the keys of `object`.
3079      * @param {Function} symbolsFunc The function to get the symbols of `object`.
3080      * @returns {Array} Returns the array of property names and symbols.
3081      */
3082     function baseGetAllKeys(object, keysFunc, symbolsFunc) {
3083       var result = keysFunc(object);
3084       return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
3085     }
3086
3087     /**
3088      * The base implementation of `getTag` without fallbacks for buggy environments.
3089      *
3090      * @private
3091      * @param {*} value The value to query.
3092      * @returns {string} Returns the `toStringTag`.
3093      */
3094     function baseGetTag(value) {
3095       if (value == null) {
3096         return value === undefined ? undefinedTag : nullTag;
3097       }
3098       return (symToStringTag && symToStringTag in Object(value))
3099         ? getRawTag(value)
3100         : objectToString(value);
3101     }
3102
3103     /**
3104      * The base implementation of `_.gt` which doesn't coerce arguments.
3105      *
3106      * @private
3107      * @param {*} value The value to compare.
3108      * @param {*} other The other value to compare.
3109      * @returns {boolean} Returns `true` if `value` is greater than `other`,
3110      *  else `false`.
3111      */
3112     function baseGt(value, other) {
3113       return value > other;
3114     }
3115
3116     /**
3117      * The base implementation of `_.has` without support for deep paths.
3118      *
3119      * @private
3120      * @param {Object} [object] The object to query.
3121      * @param {Array|string} key The key to check.
3122      * @returns {boolean} Returns `true` if `key` exists, else `false`.
3123      */
3124     function baseHas(object, key) {
3125       return object != null && hasOwnProperty.call(object, key);
3126     }
3127
3128     /**
3129      * The base implementation of `_.hasIn` without support for deep paths.
3130      *
3131      * @private
3132      * @param {Object} [object] The object to query.
3133      * @param {Array|string} key The key to check.
3134      * @returns {boolean} Returns `true` if `key` exists, else `false`.
3135      */
3136     function baseHasIn(object, key) {
3137       return object != null && key in Object(object);
3138     }
3139
3140     /**
3141      * The base implementation of `_.inRange` which doesn't coerce arguments.
3142      *
3143      * @private
3144      * @param {number} number The number to check.
3145      * @param {number} start The start of the range.
3146      * @param {number} end The end of the range.
3147      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
3148      */
3149     function baseInRange(number, start, end) {
3150       return number >= nativeMin(start, end) && number < nativeMax(start, end);
3151     }
3152
3153     /**
3154      * The base implementation of methods like `_.intersection`, without support
3155      * for iteratee shorthands, that accepts an array of arrays to inspect.
3156      *
3157      * @private
3158      * @param {Array} arrays The arrays to inspect.
3159      * @param {Function} [iteratee] The iteratee invoked per element.
3160      * @param {Function} [comparator] The comparator invoked per element.
3161      * @returns {Array} Returns the new array of shared values.
3162      */
3163     function baseIntersection(arrays, iteratee, comparator) {
3164       var includes = comparator ? arrayIncludesWith : arrayIncludes,
3165           length = arrays[0].length,
3166           othLength = arrays.length,
3167           othIndex = othLength,
3168           caches = Array(othLength),
3169           maxLength = Infinity,
3170           result = [];
3171
3172       while (othIndex--) {
3173         var array = arrays[othIndex];
3174         if (othIndex && iteratee) {
3175           array = arrayMap(array, baseUnary(iteratee));
3176         }
3177         maxLength = nativeMin(array.length, maxLength);
3178         caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
3179           ? new SetCache(othIndex && array)
3180           : undefined;
3181       }
3182       array = arrays[0];
3183
3184       var index = -1,
3185           seen = caches[0];
3186
3187       outer:
3188       while (++index < length && result.length < maxLength) {
3189         var value = array[index],
3190             computed = iteratee ? iteratee(value) : value;
3191
3192         value = (comparator || value !== 0) ? value : 0;
3193         if (!(seen
3194               ? cacheHas(seen, computed)
3195               : includes(result, computed, comparator)
3196             )) {
3197           othIndex = othLength;
3198           while (--othIndex) {
3199             var cache = caches[othIndex];
3200             if (!(cache
3201                   ? cacheHas(cache, computed)
3202                   : includes(arrays[othIndex], computed, comparator))
3203                 ) {
3204               continue outer;
3205             }
3206           }
3207           if (seen) {
3208             seen.push(computed);
3209           }
3210           result.push(value);
3211         }
3212       }
3213       return result;
3214     }
3215
3216     /**
3217      * The base implementation of `_.invert` and `_.invertBy` which inverts
3218      * `object` with values transformed by `iteratee` and set by `setter`.
3219      *
3220      * @private
3221      * @param {Object} object The object to iterate over.
3222      * @param {Function} setter The function to set `accumulator` values.
3223      * @param {Function} iteratee The iteratee to transform values.
3224      * @param {Object} accumulator The initial inverted object.
3225      * @returns {Function} Returns `accumulator`.
3226      */
3227     function baseInverter(object, setter, iteratee, accumulator) {
3228       baseForOwn(object, function(value, key, object) {
3229         setter(accumulator, iteratee(value), key, object);
3230       });
3231       return accumulator;
3232     }
3233
3234     /**
3235      * The base implementation of `_.invoke` without support for individual
3236      * method arguments.
3237      *
3238      * @private
3239      * @param {Object} object The object to query.
3240      * @param {Array|string} path The path of the method to invoke.
3241      * @param {Array} args The arguments to invoke the method with.
3242      * @returns {*} Returns the result of the invoked method.
3243      */
3244     function baseInvoke(object, path, args) {
3245       path = castPath(path, object);
3246       object = parent(object, path);
3247       var func = object == null ? object : object[toKey(last(path))];
3248       return func == null ? undefined : apply(func, object, args);
3249     }
3250
3251     /**
3252      * The base implementation of `_.isArguments`.
3253      *
3254      * @private
3255      * @param {*} value The value to check.
3256      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3257      */
3258     function baseIsArguments(value) {
3259       return isObjectLike(value) && baseGetTag(value) == argsTag;
3260     }
3261
3262     /**
3263      * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
3264      *
3265      * @private
3266      * @param {*} value The value to check.
3267      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
3268      */
3269     function baseIsArrayBuffer(value) {
3270       return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
3271     }
3272
3273     /**
3274      * The base implementation of `_.isDate` without Node.js optimizations.
3275      *
3276      * @private
3277      * @param {*} value The value to check.
3278      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
3279      */
3280     function baseIsDate(value) {
3281       return isObjectLike(value) && baseGetTag(value) == dateTag;
3282     }
3283
3284     /**
3285      * The base implementation of `_.isEqual` which supports partial comparisons
3286      * and tracks traversed objects.
3287      *
3288      * @private
3289      * @param {*} value The value to compare.
3290      * @param {*} other The other value to compare.
3291      * @param {boolean} bitmask The bitmask flags.
3292      *  1 - Unordered comparison
3293      *  2 - Partial comparison
3294      * @param {Function} [customizer] The function to customize comparisons.
3295      * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3296      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3297      */
3298     function baseIsEqual(value, other, bitmask, customizer, stack) {
3299       if (value === other) {
3300         return true;
3301       }
3302       if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
3303         return value !== value && other !== other;
3304       }
3305       return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3306     }
3307
3308     /**
3309      * A specialized version of `baseIsEqual` for arrays and objects which performs
3310      * deep comparisons and tracks traversed objects enabling objects with circular
3311      * references to be compared.
3312      *
3313      * @private
3314      * @param {Object} object The object to compare.
3315      * @param {Object} other The other object to compare.
3316      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3317      * @param {Function} customizer The function to customize comparisons.
3318      * @param {Function} equalFunc The function to determine equivalents of values.
3319      * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3320      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3321      */
3322     function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3323       var objIsArr = isArray(object),
3324           othIsArr = isArray(other),
3325           objTag = objIsArr ? arrayTag : getTag(object),
3326           othTag = othIsArr ? arrayTag : getTag(other);
3327
3328       objTag = objTag == argsTag ? objectTag : objTag;
3329       othTag = othTag == argsTag ? objectTag : othTag;
3330
3331       var objIsObj = objTag == objectTag,
3332           othIsObj = othTag == objectTag,
3333           isSameTag = objTag == othTag;
3334
3335       if (isSameTag && isBuffer(object)) {
3336         if (!isBuffer(other)) {
3337           return false;
3338         }
3339         objIsArr = true;
3340         objIsObj = false;
3341       }
3342       if (isSameTag && !objIsObj) {
3343         stack || (stack = new Stack);
3344         return (objIsArr || isTypedArray(object))
3345           ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3346           : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3347       }
3348       if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3349         var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3350             othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3351
3352         if (objIsWrapped || othIsWrapped) {
3353           var objUnwrapped = objIsWrapped ? object.value() : object,
3354               othUnwrapped = othIsWrapped ? other.value() : other;
3355
3356           stack || (stack = new Stack);
3357           return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3358         }
3359       }
3360       if (!isSameTag) {
3361         return false;
3362       }
3363       stack || (stack = new Stack);
3364       return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3365     }
3366
3367     /**
3368      * The base implementation of `_.isMap` without Node.js optimizations.
3369      *
3370      * @private
3371      * @param {*} value The value to check.
3372      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
3373      */
3374     function baseIsMap(value) {
3375       return isObjectLike(value) && getTag(value) == mapTag;
3376     }
3377
3378     /**
3379      * The base implementation of `_.isMatch` without support for iteratee shorthands.
3380      *
3381      * @private
3382      * @param {Object} object The object to inspect.
3383      * @param {Object} source The object of property values to match.
3384      * @param {Array} matchData The property names, values, and compare flags to match.
3385      * @param {Function} [customizer] The function to customize comparisons.
3386      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
3387      */
3388     function baseIsMatch(object, source, matchData, customizer) {
3389       var index = matchData.length,
3390           length = index,
3391           noCustomizer = !customizer;
3392
3393       if (object == null) {
3394         return !length;
3395       }
3396       object = Object(object);
3397       while (index--) {
3398         var data = matchData[index];
3399         if ((noCustomizer && data[2])
3400               ? data[1] !== object[data[0]]
3401               : !(data[0] in object)
3402             ) {
3403           return false;
3404         }
3405       }
3406       while (++index < length) {
3407         data = matchData[index];
3408         var key = data[0],
3409             objValue = object[key],
3410             srcValue = data[1];
3411
3412         if (noCustomizer && data[2]) {
3413           if (objValue === undefined && !(key in object)) {
3414             return false;
3415           }
3416         } else {
3417           var stack = new Stack;
3418           if (customizer) {
3419             var result = customizer(objValue, srcValue, key, object, source, stack);
3420           }
3421           if (!(result === undefined
3422                 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
3423                 : result
3424               )) {
3425             return false;
3426           }
3427         }
3428       }
3429       return true;
3430     }
3431
3432     /**
3433      * The base implementation of `_.isNative` without bad shim checks.
3434      *
3435      * @private
3436      * @param {*} value The value to check.
3437      * @returns {boolean} Returns `true` if `value` is a native function,
3438      *  else `false`.
3439      */
3440     function baseIsNative(value) {
3441       if (!isObject(value) || isMasked(value)) {
3442         return false;
3443       }
3444       var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3445       return pattern.test(toSource(value));
3446     }
3447
3448     /**
3449      * The base implementation of `_.isRegExp` without Node.js optimizations.
3450      *
3451      * @private
3452      * @param {*} value The value to check.
3453      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
3454      */
3455     function baseIsRegExp(value) {
3456       return isObjectLike(value) && baseGetTag(value) == regexpTag;
3457     }
3458
3459     /**
3460      * The base implementation of `_.isSet` without Node.js optimizations.
3461      *
3462      * @private
3463      * @param {*} value The value to check.
3464      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
3465      */
3466     function baseIsSet(value) {
3467       return isObjectLike(value) && getTag(value) == setTag;
3468     }
3469
3470     /**
3471      * The base implementation of `_.isTypedArray` without Node.js optimizations.
3472      *
3473      * @private
3474      * @param {*} value The value to check.
3475      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3476      */
3477     function baseIsTypedArray(value) {
3478       return isObjectLike(value) &&
3479         isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3480     }
3481
3482     /**
3483      * The base implementation of `_.iteratee`.
3484      *
3485      * @private
3486      * @param {*} [value=_.identity] The value to convert to an iteratee.
3487      * @returns {Function} Returns the iteratee.
3488      */
3489     function baseIteratee(value) {
3490       // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
3491       // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
3492       if (typeof value == 'function') {
3493         return value;
3494       }
3495       if (value == null) {
3496         return identity;
3497       }
3498       if (typeof value == 'object') {
3499         return isArray(value)
3500           ? baseMatchesProperty(value[0], value[1])
3501           : baseMatches(value);
3502       }
3503       return property(value);
3504     }
3505
3506     /**
3507      * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3508      *
3509      * @private
3510      * @param {Object} object The object to query.
3511      * @returns {Array} Returns the array of property names.
3512      */
3513     function baseKeys(object) {
3514       if (!isPrototype(object)) {
3515         return nativeKeys(object);
3516       }
3517       var result = [];
3518       for (var key in Object(object)) {
3519         if (hasOwnProperty.call(object, key) && key != 'constructor') {
3520           result.push(key);
3521         }
3522       }
3523       return result;
3524     }
3525
3526     /**
3527      * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3528      *
3529      * @private
3530      * @param {Object} object The object to query.
3531      * @returns {Array} Returns the array of property names.
3532      */
3533     function baseKeysIn(object) {
3534       if (!isObject(object)) {
3535         return nativeKeysIn(object);
3536       }
3537       var isProto = isPrototype(object),
3538           result = [];
3539
3540       for (var key in object) {
3541         if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
3542           result.push(key);
3543         }
3544       }
3545       return result;
3546     }
3547
3548     /**
3549      * The base implementation of `_.lt` which doesn't coerce arguments.
3550      *
3551      * @private
3552      * @param {*} value The value to compare.
3553      * @param {*} other The other value to compare.
3554      * @returns {boolean} Returns `true` if `value` is less than `other`,
3555      *  else `false`.
3556      */
3557     function baseLt(value, other) {
3558       return value < other;
3559     }
3560
3561     /**
3562      * The base implementation of `_.map` without support for iteratee shorthands.
3563      *
3564      * @private
3565      * @param {Array|Object} collection The collection to iterate over.
3566      * @param {Function} iteratee The function invoked per iteration.
3567      * @returns {Array} Returns the new mapped array.
3568      */
3569     function baseMap(collection, iteratee) {
3570       var index = -1,
3571           result = isArrayLike(collection) ? Array(collection.length) : [];
3572
3573       baseEach(collection, function(value, key, collection) {
3574         result[++index] = iteratee(value, key, collection);
3575       });
3576       return result;
3577     }
3578
3579     /**
3580      * The base implementation of `_.matches` which doesn't clone `source`.
3581      *
3582      * @private
3583      * @param {Object} source The object of property values to match.
3584      * @returns {Function} Returns the new spec function.
3585      */
3586     function baseMatches(source) {
3587       var matchData = getMatchData(source);
3588       if (matchData.length == 1 && matchData[0][2]) {
3589         return matchesStrictComparable(matchData[0][0], matchData[0][1]);
3590       }
3591       return function(object) {
3592         return object === source || baseIsMatch(object, source, matchData);
3593       };
3594     }
3595
3596     /**
3597      * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
3598      *
3599      * @private
3600      * @param {string} path The path of the property to get.
3601      * @param {*} srcValue The value to match.
3602      * @returns {Function} Returns the new spec function.
3603      */
3604     function baseMatchesProperty(path, srcValue) {
3605       if (isKey(path) && isStrictComparable(srcValue)) {
3606         return matchesStrictComparable(toKey(path), srcValue);
3607       }
3608       return function(object) {
3609         var objValue = get(object, path);
3610         return (objValue === undefined && objValue === srcValue)
3611           ? hasIn(object, path)
3612           : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
3613       };
3614     }
3615
3616     /**
3617      * The base implementation of `_.merge` without support for multiple sources.
3618      *
3619      * @private
3620      * @param {Object} object The destination object.
3621      * @param {Object} source The source object.
3622      * @param {number} srcIndex The index of `source`.
3623      * @param {Function} [customizer] The function to customize merged values.
3624      * @param {Object} [stack] Tracks traversed source values and their merged
3625      *  counterparts.
3626      */
3627     function baseMerge(object, source, srcIndex, customizer, stack) {
3628       if (object === source) {
3629         return;
3630       }
3631       baseFor(source, function(srcValue, key) {
3632         if (isObject(srcValue)) {
3633           stack || (stack = new Stack);
3634           baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3635         }
3636         else {
3637           var newValue = customizer
3638             ? customizer(object[key], srcValue, (key + ''), object, source, stack)
3639             : undefined;
3640
3641           if (newValue === undefined) {
3642             newValue = srcValue;
3643           }
3644           assignMergeValue(object, key, newValue);
3645         }
3646       }, keysIn);
3647     }
3648
3649     /**
3650      * A specialized version of `baseMerge` for arrays and objects which performs
3651      * deep merges and tracks traversed objects enabling objects with circular
3652      * references to be merged.
3653      *
3654      * @private
3655      * @param {Object} object The destination object.
3656      * @param {Object} source The source object.
3657      * @param {string} key The key of the value to merge.
3658      * @param {number} srcIndex The index of `source`.
3659      * @param {Function} mergeFunc The function to merge values.
3660      * @param {Function} [customizer] The function to customize assigned values.
3661      * @param {Object} [stack] Tracks traversed source values and their merged
3662      *  counterparts.
3663      */
3664     function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3665       var objValue = object[key],
3666           srcValue = source[key],
3667           stacked = stack.get(srcValue);
3668
3669       if (stacked) {
3670         assignMergeValue(object, key, stacked);
3671         return;
3672       }
3673       var newValue = customizer
3674         ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3675         : undefined;
3676
3677       var isCommon = newValue === undefined;
3678
3679       if (isCommon) {
3680         var isArr = isArray(srcValue),
3681             isBuff = !isArr && isBuffer(srcValue),
3682             isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3683
3684         newValue = srcValue;
3685         if (isArr || isBuff || isTyped) {
3686           if (isArray(objValue)) {
3687             newValue = objValue;
3688           }
3689           else if (isArrayLikeObject(objValue)) {
3690             newValue = copyArray(objValue);
3691           }
3692           else if (isBuff) {
3693             isCommon = false;
3694             newValue = cloneBuffer(srcValue, true);
3695           }
3696           else if (isTyped) {
3697             isCommon = false;
3698             newValue = cloneTypedArray(srcValue, true);
3699           }
3700           else {
3701             newValue = [];
3702           }
3703         }
3704         else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3705           newValue = objValue;
3706           if (isArguments(objValue)) {
3707             newValue = toPlainObject(objValue);
3708           }
3709           else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
3710             newValue = initCloneObject(srcValue);
3711           }
3712         }
3713         else {
3714           isCommon = false;
3715         }
3716       }
3717       if (isCommon) {
3718         // Recursively merge objects and arrays (susceptible to call stack limits).
3719         stack.set(srcValue, newValue);
3720         mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3721         stack['delete'](srcValue);
3722       }
3723       assignMergeValue(object, key, newValue);
3724     }
3725
3726     /**
3727      * The base implementation of `_.nth` which doesn't coerce arguments.
3728      *
3729      * @private
3730      * @param {Array} array The array to query.
3731      * @param {number} n The index of the element to return.
3732      * @returns {*} Returns the nth element of `array`.
3733      */
3734     function baseNth(array, n) {
3735       var length = array.length;
3736       if (!length) {
3737         return;
3738       }
3739       n += n < 0 ? length : 0;
3740       return isIndex(n, length) ? array[n] : undefined;
3741     }
3742
3743     /**
3744      * The base implementation of `_.orderBy` without param guards.
3745      *
3746      * @private
3747      * @param {Array|Object} collection The collection to iterate over.
3748      * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
3749      * @param {string[]} orders The sort orders of `iteratees`.
3750      * @returns {Array} Returns the new sorted array.
3751      */
3752     function baseOrderBy(collection, iteratees, orders) {
3753       var index = -1;
3754       iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
3755
3756       var result = baseMap(collection, function(value, key, collection) {
3757         var criteria = arrayMap(iteratees, function(iteratee) {
3758           return iteratee(value);
3759         });
3760         return { 'criteria': criteria, 'index': ++index, 'value': value };
3761       });
3762
3763       return baseSortBy(result, function(object, other) {
3764         return compareMultiple(object, other, orders);
3765       });
3766     }
3767
3768     /**
3769      * The base implementation of `_.pick` without support for individual
3770      * property identifiers.
3771      *
3772      * @private
3773      * @param {Object} object The source object.
3774      * @param {string[]} paths The property paths to pick.
3775      * @returns {Object} Returns the new object.
3776      */
3777     function basePick(object, paths) {
3778       return basePickBy(object, paths, function(value, path) {
3779         return hasIn(object, path);
3780       });
3781     }
3782
3783     /**
3784      * The base implementation of  `_.pickBy` without support for iteratee shorthands.
3785      *
3786      * @private
3787      * @param {Object} object The source object.
3788      * @param {string[]} paths The property paths to pick.
3789      * @param {Function} predicate The function invoked per property.
3790      * @returns {Object} Returns the new object.
3791      */
3792     function basePickBy(object, paths, predicate) {
3793       var index = -1,
3794           length = paths.length,
3795           result = {};
3796
3797       while (++index < length) {
3798         var path = paths[index],
3799             value = baseGet(object, path);
3800
3801         if (predicate(value, path)) {
3802           baseSet(result, castPath(path, object), value);
3803         }
3804       }
3805       return result;
3806     }
3807
3808     /**
3809      * A specialized version of `baseProperty` which supports deep paths.
3810      *
3811      * @private
3812      * @param {Array|string} path The path of the property to get.
3813      * @returns {Function} Returns the new accessor function.
3814      */
3815     function basePropertyDeep(path) {
3816       return function(object) {
3817         return baseGet(object, path);
3818       };
3819     }
3820
3821     /**
3822      * The base implementation of `_.pullAllBy` without support for iteratee
3823      * shorthands.
3824      *
3825      * @private
3826      * @param {Array} array The array to modify.
3827      * @param {Array} values The values to remove.
3828      * @param {Function} [iteratee] The iteratee invoked per element.
3829      * @param {Function} [comparator] The comparator invoked per element.
3830      * @returns {Array} Returns `array`.
3831      */
3832     function basePullAll(array, values, iteratee, comparator) {
3833       var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
3834           index = -1,
3835           length = values.length,
3836           seen = array;
3837
3838       if (array === values) {
3839         values = copyArray(values);
3840       }
3841       if (iteratee) {
3842         seen = arrayMap(array, baseUnary(iteratee));
3843       }
3844       while (++index < length) {
3845         var fromIndex = 0,
3846             value = values[index],
3847             computed = iteratee ? iteratee(value) : value;
3848
3849         while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
3850           if (seen !== array) {
3851             splice.call(seen, fromIndex, 1);
3852           }
3853           splice.call(array, fromIndex, 1);
3854         }
3855       }
3856       return array;
3857     }
3858
3859     /**
3860      * The base implementation of `_.pullAt` without support for individual
3861      * indexes or capturing the removed elements.
3862      *
3863      * @private
3864      * @param {Array} array The array to modify.
3865      * @param {number[]} indexes The indexes of elements to remove.
3866      * @returns {Array} Returns `array`.
3867      */
3868     function basePullAt(array, indexes) {
3869       var length = array ? indexes.length : 0,
3870           lastIndex = length - 1;
3871
3872       while (length--) {
3873         var index = indexes[length];
3874         if (length == lastIndex || index !== previous) {
3875           var previous = index;
3876           if (isIndex(index)) {
3877             splice.call(array, index, 1);
3878           } else {
3879             baseUnset(array, index);
3880           }
3881         }
3882       }
3883       return array;
3884     }
3885
3886     /**
3887      * The base implementation of `_.random` without support for returning
3888      * floating-point numbers.
3889      *
3890      * @private
3891      * @param {number} lower The lower bound.
3892      * @param {number} upper The upper bound.
3893      * @returns {number} Returns the random number.
3894      */
3895     function baseRandom(lower, upper) {
3896       return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3897     }
3898
3899     /**
3900      * The base implementation of `_.range` and `_.rangeRight` which doesn't
3901      * coerce arguments.
3902      *
3903      * @private
3904      * @param {number} start The start of the range.
3905      * @param {number} end The end of the range.
3906      * @param {number} step The value to increment or decrement by.
3907      * @param {boolean} [fromRight] Specify iterating from right to left.
3908      * @returns {Array} Returns the range of numbers.
3909      */
3910     function baseRange(start, end, step, fromRight) {
3911       var index = -1,
3912           length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3913           result = Array(length);
3914
3915       while (length--) {
3916         result[fromRight ? length : ++index] = start;
3917         start += step;
3918       }
3919       return result;
3920     }
3921
3922     /**
3923      * The base implementation of `_.repeat` which doesn't coerce arguments.
3924      *
3925      * @private
3926      * @param {string} string The string to repeat.
3927      * @param {number} n The number of times to repeat the string.
3928      * @returns {string} Returns the repeated string.
3929      */
3930     function baseRepeat(string, n) {
3931       var result = '';
3932       if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3933         return result;
3934       }
3935       // Leverage the exponentiation by squaring algorithm for a faster repeat.
3936       // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3937       do {
3938         if (n % 2) {
3939           result += string;
3940         }
3941         n = nativeFloor(n / 2);
3942         if (n) {
3943           string += string;
3944         }
3945       } while (n);
3946
3947       return result;
3948     }
3949
3950     /**
3951      * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3952      *
3953      * @private
3954      * @param {Function} func The function to apply a rest parameter to.
3955      * @param {number} [start=func.length-1] The start position of the rest parameter.
3956      * @returns {Function} Returns the new function.
3957      */
3958     function baseRest(func, start) {
3959       return setToString(overRest(func, start, identity), func + '');
3960     }
3961
3962     /**
3963      * The base implementation of `_.sample`.
3964      *
3965      * @private
3966      * @param {Array|Object} collection The collection to sample.
3967      * @returns {*} Returns the random element.
3968      */
3969     function baseSample(collection) {
3970       return arraySample(values(collection));
3971     }
3972
3973     /**
3974      * The base implementation of `_.sampleSize` without param guards.
3975      *
3976      * @private
3977      * @param {Array|Object} collection The collection to sample.
3978      * @param {number} n The number of elements to sample.
3979      * @returns {Array} Returns the random elements.
3980      */
3981     function baseSampleSize(collection, n) {
3982       var array = values(collection);
3983       return shuffleSelf(array, baseClamp(n, 0, array.length));
3984     }
3985
3986     /**
3987      * The base implementation of `_.set`.
3988      *
3989      * @private
3990      * @param {Object} object The object to modify.
3991      * @param {Array|string} path The path of the property to set.
3992      * @param {*} value The value to set.
3993      * @param {Function} [customizer] The function to customize path creation.
3994      * @returns {Object} Returns `object`.
3995      */
3996     function baseSet(object, path, value, customizer) {
3997       if (!isObject(object)) {
3998         return object;
3999       }
4000       path = castPath(path, object);
4001
4002       var index = -1,
4003           length = path.length,
4004           lastIndex = length - 1,
4005           nested = object;
4006
4007       while (nested != null && ++index < length) {
4008         var key = toKey(path[index]),
4009             newValue = value;
4010
4011         if (index != lastIndex) {
4012           var objValue = nested[key];
4013           newValue = customizer ? customizer(objValue, key, nested) : undefined;
4014           if (newValue === undefined) {
4015             newValue = isObject(objValue)
4016               ? objValue
4017               : (isIndex(path[index + 1]) ? [] : {});
4018           }
4019         }
4020         assignValue(nested, key, newValue);
4021         nested = nested[key];
4022       }
4023       return object;
4024     }
4025
4026     /**
4027      * The base implementation of `setData` without support for hot loop shorting.
4028      *
4029      * @private
4030      * @param {Function} func The function to associate metadata with.
4031      * @param {*} data The metadata.
4032      * @returns {Function} Returns `func`.
4033      */
4034     var baseSetData = !metaMap ? identity : function(func, data) {
4035       metaMap.set(func, data);
4036       return func;
4037     };
4038
4039     /**
4040      * The base implementation of `setToString` without support for hot loop shorting.
4041      *
4042      * @private
4043      * @param {Function} func The function to modify.
4044      * @param {Function} string The `toString` result.
4045      * @returns {Function} Returns `func`.
4046      */
4047     var baseSetToString = !defineProperty ? identity : function(func, string) {
4048       return defineProperty(func, 'toString', {
4049         'configurable': true,
4050         'enumerable': false,
4051         'value': constant(string),
4052         'writable': true
4053       });
4054     };
4055
4056     /**
4057      * The base implementation of `_.shuffle`.
4058      *
4059      * @private
4060      * @param {Array|Object} collection The collection to shuffle.
4061      * @returns {Array} Returns the new shuffled array.
4062      */
4063     function baseShuffle(collection) {
4064       return shuffleSelf(values(collection));
4065     }
4066
4067     /**
4068      * The base implementation of `_.slice` without an iteratee call guard.
4069      *
4070      * @private
4071      * @param {Array} array The array to slice.
4072      * @param {number} [start=0] The start position.
4073      * @param {number} [end=array.length] The end position.
4074      * @returns {Array} Returns the slice of `array`.
4075      */
4076     function baseSlice(array, start, end) {
4077       var index = -1,
4078           length = array.length;
4079
4080       if (start < 0) {
4081         start = -start > length ? 0 : (length + start);
4082       }
4083       end = end > length ? length : end;
4084       if (end < 0) {
4085         end += length;
4086       }
4087       length = start > end ? 0 : ((end - start) >>> 0);
4088       start >>>= 0;
4089
4090       var result = Array(length);
4091       while (++index < length) {
4092         result[index] = array[index + start];
4093       }
4094       return result;
4095     }
4096
4097     /**
4098      * The base implementation of `_.some` without support for iteratee shorthands.
4099      *
4100      * @private
4101      * @param {Array|Object} collection The collection to iterate over.
4102      * @param {Function} predicate The function invoked per iteration.
4103      * @returns {boolean} Returns `true` if any element passes the predicate check,
4104      *  else `false`.
4105      */
4106     function baseSome(collection, predicate) {
4107       var result;
4108
4109       baseEach(collection, function(value, index, collection) {
4110         result = predicate(value, index, collection);
4111         return !result;
4112       });
4113       return !!result;
4114     }
4115
4116     /**
4117      * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4118      * performs a binary search of `array` to determine the index at which `value`
4119      * should be inserted into `array` in order to maintain its sort order.
4120      *
4121      * @private
4122      * @param {Array} array The sorted array to inspect.
4123      * @param {*} value The value to evaluate.
4124      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4125      * @returns {number} Returns the index at which `value` should be inserted
4126      *  into `array`.
4127      */
4128     function baseSortedIndex(array, value, retHighest) {
4129       var low = 0,
4130           high = array == null ? low : array.length;
4131
4132       if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4133         while (low < high) {
4134           var mid = (low + high) >>> 1,
4135               computed = array[mid];
4136
4137           if (computed !== null && !isSymbol(computed) &&
4138               (retHighest ? (computed <= value) : (computed < value))) {
4139             low = mid + 1;
4140           } else {
4141             high = mid;
4142           }
4143         }
4144         return high;
4145       }
4146       return baseSortedIndexBy(array, value, identity, retHighest);
4147     }
4148
4149     /**
4150      * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4151      * which invokes `iteratee` for `value` and each element of `array` to compute
4152      * their sort ranking. The iteratee is invoked with one argument; (value).
4153      *
4154      * @private
4155      * @param {Array} array The sorted array to inspect.
4156      * @param {*} value The value to evaluate.
4157      * @param {Function} iteratee The iteratee invoked per element.
4158      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4159      * @returns {number} Returns the index at which `value` should be inserted
4160      *  into `array`.
4161      */
4162     function baseSortedIndexBy(array, value, iteratee, retHighest) {
4163       value = iteratee(value);
4164
4165       var low = 0,
4166           high = array == null ? 0 : array.length,
4167           valIsNaN = value !== value,
4168           valIsNull = value === null,
4169           valIsSymbol = isSymbol(value),
4170           valIsUndefined = value === undefined;
4171
4172       while (low < high) {
4173         var mid = nativeFloor((low + high) / 2),
4174             computed = iteratee(array[mid]),
4175             othIsDefined = computed !== undefined,
4176             othIsNull = computed === null,
4177             othIsReflexive = computed === computed,
4178             othIsSymbol = isSymbol(computed);
4179
4180         if (valIsNaN) {
4181           var setLow = retHighest || othIsReflexive;
4182         } else if (valIsUndefined) {
4183           setLow = othIsReflexive && (retHighest || othIsDefined);
4184         } else if (valIsNull) {
4185           setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4186         } else if (valIsSymbol) {
4187           setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4188         } else if (othIsNull || othIsSymbol) {
4189           setLow = false;
4190         } else {
4191           setLow = retHighest ? (computed <= value) : (computed < value);
4192         }
4193         if (setLow) {
4194           low = mid + 1;
4195         } else {
4196           high = mid;
4197         }
4198       }
4199       return nativeMin(high, MAX_ARRAY_INDEX);
4200     }
4201
4202     /**
4203      * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4204      * support for iteratee shorthands.
4205      *
4206      * @private
4207      * @param {Array} array The array to inspect.
4208      * @param {Function} [iteratee] The iteratee invoked per element.
4209      * @returns {Array} Returns the new duplicate free array.
4210      */
4211     function baseSortedUniq(array, iteratee) {
4212       var index = -1,
4213           length = array.length,
4214           resIndex = 0,
4215           result = [];
4216
4217       while (++index < length) {
4218         var value = array[index],
4219             computed = iteratee ? iteratee(value) : value;
4220
4221         if (!index || !eq(computed, seen)) {
4222           var seen = computed;
4223           result[resIndex++] = value === 0 ? 0 : value;
4224         }
4225       }
4226       return result;
4227     }
4228
4229     /**
4230      * The base implementation of `_.toNumber` which doesn't ensure correct
4231      * conversions of binary, hexadecimal, or octal string values.
4232      *
4233      * @private
4234      * @param {*} value The value to process.
4235      * @returns {number} Returns the number.
4236      */
4237     function baseToNumber(value) {
4238       if (typeof value == 'number') {
4239         return value;
4240       }
4241       if (isSymbol(value)) {
4242         return NAN;
4243       }
4244       return +value;
4245     }
4246
4247     /**
4248      * The base implementation of `_.toString` which doesn't convert nullish
4249      * values to empty strings.
4250      *
4251      * @private
4252      * @param {*} value The value to process.
4253      * @returns {string} Returns the string.
4254      */
4255     function baseToString(value) {
4256       // Exit early for strings to avoid a performance hit in some environments.
4257       if (typeof value == 'string') {
4258         return value;
4259       }
4260       if (isArray(value)) {
4261         // Recursively convert values (susceptible to call stack limits).
4262         return arrayMap(value, baseToString) + '';
4263       }
4264       if (isSymbol(value)) {
4265         return symbolToString ? symbolToString.call(value) : '';
4266       }
4267       var result = (value + '');
4268       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4269     }
4270
4271     /**
4272      * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4273      *
4274      * @private
4275      * @param {Array} array The array to inspect.
4276      * @param {Function} [iteratee] The iteratee invoked per element.
4277      * @param {Function} [comparator] The comparator invoked per element.
4278      * @returns {Array} Returns the new duplicate free array.
4279      */
4280     function baseUniq(array, iteratee, comparator) {
4281       var index = -1,
4282           includes = arrayIncludes,
4283           length = array.length,
4284           isCommon = true,
4285           result = [],
4286           seen = result;
4287
4288       if (comparator) {
4289         isCommon = false;
4290         includes = arrayIncludesWith;
4291       }
4292       else if (length >= LARGE_ARRAY_SIZE) {
4293         var set = iteratee ? null : createSet(array);
4294         if (set) {
4295           return setToArray(set);
4296         }
4297         isCommon = false;
4298         includes = cacheHas;
4299         seen = new SetCache;
4300       }
4301       else {
4302         seen = iteratee ? [] : result;
4303       }
4304       outer:
4305       while (++index < length) {
4306         var value = array[index],
4307             computed = iteratee ? iteratee(value) : value;
4308
4309         value = (comparator || value !== 0) ? value : 0;
4310         if (isCommon && computed === computed) {
4311           var seenIndex = seen.length;
4312           while (seenIndex--) {
4313             if (seen[seenIndex] === computed) {
4314               continue outer;
4315             }
4316           }
4317           if (iteratee) {
4318             seen.push(computed);
4319           }
4320           result.push(value);
4321         }
4322         else if (!includes(seen, computed, comparator)) {
4323           if (seen !== result) {
4324             seen.push(computed);
4325           }
4326           result.push(value);
4327         }
4328       }
4329       return result;
4330     }
4331
4332     /**
4333      * The base implementation of `_.unset`.
4334      *
4335      * @private
4336      * @param {Object} object The object to modify.
4337      * @param {Array|string} path The property path to unset.
4338      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4339      */
4340     function baseUnset(object, path) {
4341       path = castPath(path, object);
4342       object = parent(object, path);
4343       return object == null || delete object[toKey(last(path))];
4344     }
4345
4346     /**
4347      * The base implementation of `_.update`.
4348      *
4349      * @private
4350      * @param {Object} object The object to modify.
4351      * @param {Array|string} path The path of the property to update.
4352      * @param {Function} updater The function to produce the updated value.
4353      * @param {Function} [customizer] The function to customize path creation.
4354      * @returns {Object} Returns `object`.
4355      */
4356     function baseUpdate(object, path, updater, customizer) {
4357       return baseSet(object, path, updater(baseGet(object, path)), customizer);
4358     }
4359
4360     /**
4361      * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4362      * without support for iteratee shorthands.
4363      *
4364      * @private
4365      * @param {Array} array The array to query.
4366      * @param {Function} predicate The function invoked per iteration.
4367      * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4368      * @param {boolean} [fromRight] Specify iterating from right to left.
4369      * @returns {Array} Returns the slice of `array`.
4370      */
4371     function baseWhile(array, predicate, isDrop, fromRight) {
4372       var length = array.length,
4373           index = fromRight ? length : -1;
4374
4375       while ((fromRight ? index-- : ++index < length) &&
4376         predicate(array[index], index, array)) {}
4377
4378       return isDrop
4379         ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4380         : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4381     }
4382
4383     /**
4384      * The base implementation of `wrapperValue` which returns the result of
4385      * performing a sequence of actions on the unwrapped `value`, where each
4386      * successive action is supplied the return value of the previous.
4387      *
4388      * @private
4389      * @param {*} value The unwrapped value.
4390      * @param {Array} actions Actions to perform to resolve the unwrapped value.
4391      * @returns {*} Returns the resolved value.
4392      */
4393     function baseWrapperValue(value, actions) {
4394       var result = value;
4395       if (result instanceof LazyWrapper) {
4396         result = result.value();
4397       }
4398       return arrayReduce(actions, function(result, action) {
4399         return action.func.apply(action.thisArg, arrayPush([result], action.args));
4400       }, result);
4401     }
4402
4403     /**
4404      * The base implementation of methods like `_.xor`, without support for
4405      * iteratee shorthands, that accepts an array of arrays to inspect.
4406      *
4407      * @private
4408      * @param {Array} arrays The arrays to inspect.
4409      * @param {Function} [iteratee] The iteratee invoked per element.
4410      * @param {Function} [comparator] The comparator invoked per element.
4411      * @returns {Array} Returns the new array of values.
4412      */
4413     function baseXor(arrays, iteratee, comparator) {
4414       var length = arrays.length;
4415       if (length < 2) {
4416         return length ? baseUniq(arrays[0]) : [];
4417       }
4418       var index = -1,
4419           result = Array(length);
4420
4421       while (++index < length) {
4422         var array = arrays[index],
4423             othIndex = -1;
4424
4425         while (++othIndex < length) {
4426           if (othIndex != index) {
4427             result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4428           }
4429         }
4430       }
4431       return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4432     }
4433
4434     /**
4435      * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4436      *
4437      * @private
4438      * @param {Array} props The property identifiers.
4439      * @param {Array} values The property values.
4440      * @param {Function} assignFunc The function to assign values.
4441      * @returns {Object} Returns the new object.
4442      */
4443     function baseZipObject(props, values, assignFunc) {
4444       var index = -1,
4445           length = props.length,
4446           valsLength = values.length,
4447           result = {};
4448
4449       while (++index < length) {
4450         var value = index < valsLength ? values[index] : undefined;
4451         assignFunc(result, props[index], value);
4452       }
4453       return result;
4454     }
4455
4456     /**
4457      * Casts `value` to an empty array if it's not an array like object.
4458      *
4459      * @private
4460      * @param {*} value The value to inspect.
4461      * @returns {Array|Object} Returns the cast array-like object.
4462      */
4463     function castArrayLikeObject(value) {
4464       return isArrayLikeObject(value) ? value : [];
4465     }
4466
4467     /**
4468      * Casts `value` to `identity` if it's not a function.
4469      *
4470      * @private
4471      * @param {*} value The value to inspect.
4472      * @returns {Function} Returns cast function.
4473      */
4474     function castFunction(value) {
4475       return typeof value == 'function' ? value : identity;
4476     }
4477
4478     /**
4479      * Casts `value` to a path array if it's not one.
4480      *
4481      * @private
4482      * @param {*} value The value to inspect.
4483      * @param {Object} [object] The object to query keys on.
4484      * @returns {Array} Returns the cast property path array.
4485      */
4486     function castPath(value, object) {
4487       if (isArray(value)) {
4488         return value;
4489       }
4490       return isKey(value, object) ? [value] : stringToPath(toString(value));
4491     }
4492
4493     /**
4494      * A `baseRest` alias which can be replaced with `identity` by module
4495      * replacement plugins.
4496      *
4497      * @private
4498      * @type {Function}
4499      * @param {Function} func The function to apply a rest parameter to.
4500      * @returns {Function} Returns the new function.
4501      */
4502     var castRest = baseRest;
4503
4504     /**
4505      * Casts `array` to a slice if it's needed.
4506      *
4507      * @private
4508      * @param {Array} array The array to inspect.
4509      * @param {number} start The start position.
4510      * @param {number} [end=array.length] The end position.
4511      * @returns {Array} Returns the cast slice.
4512      */
4513     function castSlice(array, start, end) {
4514       var length = array.length;
4515       end = end === undefined ? length : end;
4516       return (!start && end >= length) ? array : baseSlice(array, start, end);
4517     }
4518
4519     /**
4520      * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4521      *
4522      * @private
4523      * @param {number|Object} id The timer id or timeout object of the timer to clear.
4524      */
4525     var clearTimeout = ctxClearTimeout || function(id) {
4526       return root.clearTimeout(id);
4527     };
4528
4529     /**
4530      * Creates a clone of  `buffer`.
4531      *
4532      * @private
4533      * @param {Buffer} buffer The buffer to clone.
4534      * @param {boolean} [isDeep] Specify a deep clone.
4535      * @returns {Buffer} Returns the cloned buffer.
4536      */
4537     function cloneBuffer(buffer, isDeep) {
4538       if (isDeep) {
4539         return buffer.slice();
4540       }
4541       var length = buffer.length,
4542           result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4543
4544       buffer.copy(result);
4545       return result;
4546     }
4547
4548     /**
4549      * Creates a clone of `arrayBuffer`.
4550      *
4551      * @private
4552      * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4553      * @returns {ArrayBuffer} Returns the cloned array buffer.
4554      */
4555     function cloneArrayBuffer(arrayBuffer) {
4556       var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4557       new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4558       return result;
4559     }
4560
4561     /**
4562      * Creates a clone of `dataView`.
4563      *
4564      * @private
4565      * @param {Object} dataView The data view to clone.
4566      * @param {boolean} [isDeep] Specify a deep clone.
4567      * @returns {Object} Returns the cloned data view.
4568      */
4569     function cloneDataView(dataView, isDeep) {
4570       var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4571       return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4572     }
4573
4574     /**
4575      * Creates a clone of `map`.
4576      *
4577      * @private
4578      * @param {Object} map The map to clone.
4579      * @param {Function} cloneFunc The function to clone values.
4580      * @param {boolean} [isDeep] Specify a deep clone.
4581      * @returns {Object} Returns the cloned map.
4582      */
4583     function cloneMap(map, isDeep, cloneFunc) {
4584       var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4585       return arrayReduce(array, addMapEntry, new map.constructor);
4586     }
4587
4588     /**
4589      * Creates a clone of `regexp`.
4590      *
4591      * @private
4592      * @param {Object} regexp The regexp to clone.
4593      * @returns {Object} Returns the cloned regexp.
4594      */
4595     function cloneRegExp(regexp) {
4596       var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4597       result.lastIndex = regexp.lastIndex;
4598       return result;
4599     }
4600
4601     /**
4602      * Creates a clone of `set`.
4603      *
4604      * @private
4605      * @param {Object} set The set to clone.
4606      * @param {Function} cloneFunc The function to clone values.
4607      * @param {boolean} [isDeep] Specify a deep clone.
4608      * @returns {Object} Returns the cloned set.
4609      */
4610     function cloneSet(set, isDeep, cloneFunc) {
4611       var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4612       return arrayReduce(array, addSetEntry, new set.constructor);
4613     }
4614
4615     /**
4616      * Creates a clone of the `symbol` object.
4617      *
4618      * @private
4619      * @param {Object} symbol The symbol object to clone.
4620      * @returns {Object} Returns the cloned symbol object.
4621      */
4622     function cloneSymbol(symbol) {
4623       return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4624     }
4625
4626     /**
4627      * Creates a clone of `typedArray`.
4628      *
4629      * @private
4630      * @param {Object} typedArray The typed array to clone.
4631      * @param {boolean} [isDeep] Specify a deep clone.
4632      * @returns {Object} Returns the cloned typed array.
4633      */
4634     function cloneTypedArray(typedArray, isDeep) {
4635       var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4636       return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4637     }
4638
4639     /**
4640      * Compares values to sort them in ascending order.
4641      *
4642      * @private
4643      * @param {*} value The value to compare.
4644      * @param {*} other The other value to compare.
4645      * @returns {number} Returns the sort order indicator for `value`.
4646      */
4647     function compareAscending(value, other) {
4648       if (value !== other) {
4649         var valIsDefined = value !== undefined,
4650             valIsNull = value === null,
4651             valIsReflexive = value === value,
4652             valIsSymbol = isSymbol(value);
4653
4654         var othIsDefined = other !== undefined,
4655             othIsNull = other === null,
4656             othIsReflexive = other === other,
4657             othIsSymbol = isSymbol(other);
4658
4659         if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4660             (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4661             (valIsNull && othIsDefined && othIsReflexive) ||
4662             (!valIsDefined && othIsReflexive) ||
4663             !valIsReflexive) {
4664           return 1;
4665         }
4666         if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4667             (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4668             (othIsNull && valIsDefined && valIsReflexive) ||
4669             (!othIsDefined && valIsReflexive) ||
4670             !othIsReflexive) {
4671           return -1;
4672         }
4673       }
4674       return 0;
4675     }
4676
4677     /**
4678      * Used by `_.orderBy` to compare multiple properties of a value to another
4679      * and stable sort them.
4680      *
4681      * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4682      * specify an order of "desc" for descending or "asc" for ascending sort order
4683      * of corresponding values.
4684      *
4685      * @private
4686      * @param {Object} object The object to compare.
4687      * @param {Object} other The other object to compare.
4688      * @param {boolean[]|string[]} orders The order to sort by for each property.
4689      * @returns {number} Returns the sort order indicator for `object`.
4690      */
4691     function compareMultiple(object, other, orders) {
4692       var index = -1,
4693           objCriteria = object.criteria,
4694           othCriteria = other.criteria,
4695           length = objCriteria.length,
4696           ordersLength = orders.length;
4697
4698       while (++index < length) {
4699         var result = compareAscending(objCriteria[index], othCriteria[index]);
4700         if (result) {
4701           if (index >= ordersLength) {
4702             return result;
4703           }
4704           var order = orders[index];
4705           return result * (order == 'desc' ? -1 : 1);
4706         }
4707       }
4708       // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4709       // that causes it, under certain circumstances, to provide the same value for
4710       // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4711       // for more details.
4712       //
4713       // This also ensures a stable sort in V8 and other engines.
4714       // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4715       return object.index - other.index;
4716     }
4717
4718     /**
4719      * Creates an array that is the composition of partially applied arguments,
4720      * placeholders, and provided arguments into a single array of arguments.
4721      *
4722      * @private
4723      * @param {Array} args The provided arguments.
4724      * @param {Array} partials The arguments to prepend to those provided.
4725      * @param {Array} holders The `partials` placeholder indexes.
4726      * @params {boolean} [isCurried] Specify composing for a curried function.
4727      * @returns {Array} Returns the new array of composed arguments.
4728      */
4729     function composeArgs(args, partials, holders, isCurried) {
4730       var argsIndex = -1,
4731           argsLength = args.length,
4732           holdersLength = holders.length,
4733           leftIndex = -1,
4734           leftLength = partials.length,
4735           rangeLength = nativeMax(argsLength - holdersLength, 0),
4736           result = Array(leftLength + rangeLength),
4737           isUncurried = !isCurried;
4738
4739       while (++leftIndex < leftLength) {
4740         result[leftIndex] = partials[leftIndex];
4741       }
4742       while (++argsIndex < holdersLength) {
4743         if (isUncurried || argsIndex < argsLength) {
4744           result[holders[argsIndex]] = args[argsIndex];
4745         }
4746       }
4747       while (rangeLength--) {
4748         result[leftIndex++] = args[argsIndex++];
4749       }
4750       return result;
4751     }
4752
4753     /**
4754      * This function is like `composeArgs` except that the arguments composition
4755      * is tailored for `_.partialRight`.
4756      *
4757      * @private
4758      * @param {Array} args The provided arguments.
4759      * @param {Array} partials The arguments to append to those provided.
4760      * @param {Array} holders The `partials` placeholder indexes.
4761      * @params {boolean} [isCurried] Specify composing for a curried function.
4762      * @returns {Array} Returns the new array of composed arguments.
4763      */
4764     function composeArgsRight(args, partials, holders, isCurried) {
4765       var argsIndex = -1,
4766           argsLength = args.length,
4767           holdersIndex = -1,
4768           holdersLength = holders.length,
4769           rightIndex = -1,
4770           rightLength = partials.length,
4771           rangeLength = nativeMax(argsLength - holdersLength, 0),
4772           result = Array(rangeLength + rightLength),
4773           isUncurried = !isCurried;
4774
4775       while (++argsIndex < rangeLength) {
4776         result[argsIndex] = args[argsIndex];
4777       }
4778       var offset = argsIndex;
4779       while (++rightIndex < rightLength) {
4780         result[offset + rightIndex] = partials[rightIndex];
4781       }
4782       while (++holdersIndex < holdersLength) {
4783         if (isUncurried || argsIndex < argsLength) {
4784           result[offset + holders[holdersIndex]] = args[argsIndex++];
4785         }
4786       }
4787       return result;
4788     }
4789
4790     /**
4791      * Copies the values of `source` to `array`.
4792      *
4793      * @private
4794      * @param {Array} source The array to copy values from.
4795      * @param {Array} [array=[]] The array to copy values to.
4796      * @returns {Array} Returns `array`.
4797      */
4798     function copyArray(source, array) {
4799       var index = -1,
4800           length = source.length;
4801
4802       array || (array = Array(length));
4803       while (++index < length) {
4804         array[index] = source[index];
4805       }
4806       return array;
4807     }
4808
4809     /**
4810      * Copies properties of `source` to `object`.
4811      *
4812      * @private
4813      * @param {Object} source The object to copy properties from.
4814      * @param {Array} props The property identifiers to copy.
4815      * @param {Object} [object={}] The object to copy properties to.
4816      * @param {Function} [customizer] The function to customize copied values.
4817      * @returns {Object} Returns `object`.
4818      */
4819     function copyObject(source, props, object, customizer) {
4820       var isNew = !object;
4821       object || (object = {});
4822
4823       var index = -1,
4824           length = props.length;
4825
4826       while (++index < length) {
4827         var key = props[index];
4828
4829         var newValue = customizer
4830           ? customizer(object[key], source[key], key, object, source)
4831           : undefined;
4832
4833         if (newValue === undefined) {
4834           newValue = source[key];
4835         }
4836         if (isNew) {
4837           baseAssignValue(object, key, newValue);
4838         } else {
4839           assignValue(object, key, newValue);
4840         }
4841       }
4842       return object;
4843     }
4844
4845     /**
4846      * Copies own symbols of `source` to `object`.
4847      *
4848      * @private
4849      * @param {Object} source The object to copy symbols from.
4850      * @param {Object} [object={}] The object to copy symbols to.
4851      * @returns {Object} Returns `object`.
4852      */
4853     function copySymbols(source, object) {
4854       return copyObject(source, getSymbols(source), object);
4855     }
4856
4857     /**
4858      * Copies own and inherited symbols of `source` to `object`.
4859      *
4860      * @private
4861      * @param {Object} source The object to copy symbols from.
4862      * @param {Object} [object={}] The object to copy symbols to.
4863      * @returns {Object} Returns `object`.
4864      */
4865     function copySymbolsIn(source, object) {
4866       return copyObject(source, getSymbolsIn(source), object);
4867     }
4868
4869     /**
4870      * Creates a function like `_.groupBy`.
4871      *
4872      * @private
4873      * @param {Function} setter The function to set accumulator values.
4874      * @param {Function} [initializer] The accumulator object initializer.
4875      * @returns {Function} Returns the new aggregator function.
4876      */
4877     function createAggregator(setter, initializer) {
4878       return function(collection, iteratee) {
4879         var func = isArray(collection) ? arrayAggregator : baseAggregator,
4880             accumulator = initializer ? initializer() : {};
4881
4882         return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4883       };
4884     }
4885
4886     /**
4887      * Creates a function like `_.assign`.
4888      *
4889      * @private
4890      * @param {Function} assigner The function to assign values.
4891      * @returns {Function} Returns the new assigner function.
4892      */
4893     function createAssigner(assigner) {
4894       return baseRest(function(object, sources) {
4895         var index = -1,
4896             length = sources.length,
4897             customizer = length > 1 ? sources[length - 1] : undefined,
4898             guard = length > 2 ? sources[2] : undefined;
4899
4900         customizer = (assigner.length > 3 && typeof customizer == 'function')
4901           ? (length--, customizer)
4902           : undefined;
4903
4904         if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4905           customizer = length < 3 ? undefined : customizer;
4906           length = 1;
4907         }
4908         object = Object(object);
4909         while (++index < length) {
4910           var source = sources[index];
4911           if (source) {
4912             assigner(object, source, index, customizer);
4913           }
4914         }
4915         return object;
4916       });
4917     }
4918
4919     /**
4920      * Creates a `baseEach` or `baseEachRight` function.
4921      *
4922      * @private
4923      * @param {Function} eachFunc The function to iterate over a collection.
4924      * @param {boolean} [fromRight] Specify iterating from right to left.
4925      * @returns {Function} Returns the new base function.
4926      */
4927     function createBaseEach(eachFunc, fromRight) {
4928       return function(collection, iteratee) {
4929         if (collection == null) {
4930           return collection;
4931         }
4932         if (!isArrayLike(collection)) {
4933           return eachFunc(collection, iteratee);
4934         }
4935         var length = collection.length,
4936             index = fromRight ? length : -1,
4937             iterable = Object(collection);
4938
4939         while ((fromRight ? index-- : ++index < length)) {
4940           if (iteratee(iterable[index], index, iterable) === false) {
4941             break;
4942           }
4943         }
4944         return collection;
4945       };
4946     }
4947
4948     /**
4949      * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4950      *
4951      * @private
4952      * @param {boolean} [fromRight] Specify iterating from right to left.
4953      * @returns {Function} Returns the new base function.
4954      */
4955     function createBaseFor(fromRight) {
4956       return function(object, iteratee, keysFunc) {
4957         var index = -1,
4958             iterable = Object(object),
4959             props = keysFunc(object),
4960             length = props.length;
4961
4962         while (length--) {
4963           var key = props[fromRight ? length : ++index];
4964           if (iteratee(iterable[key], key, iterable) === false) {
4965             break;
4966           }
4967         }
4968         return object;
4969       };
4970     }
4971
4972     /**
4973      * Creates a function that wraps `func` to invoke it with the optional `this`
4974      * binding of `thisArg`.
4975      *
4976      * @private
4977      * @param {Function} func The function to wrap.
4978      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
4979      * @param {*} [thisArg] The `this` binding of `func`.
4980      * @returns {Function} Returns the new wrapped function.
4981      */
4982     function createBind(func, bitmask, thisArg) {
4983       var isBind = bitmask & WRAP_BIND_FLAG,
4984           Ctor = createCtor(func);
4985
4986       function wrapper() {
4987         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
4988         return fn.apply(isBind ? thisArg : this, arguments);
4989       }
4990       return wrapper;
4991     }
4992
4993     /**
4994      * Creates a function like `_.lowerFirst`.
4995      *
4996      * @private
4997      * @param {string} methodName The name of the `String` case method to use.
4998      * @returns {Function} Returns the new case function.
4999      */
5000     function createCaseFirst(methodName) {
5001       return function(string) {
5002         string = toString(string);
5003
5004         var strSymbols = hasUnicode(string)
5005           ? stringToArray(string)
5006           : undefined;
5007
5008         var chr = strSymbols
5009           ? strSymbols[0]
5010           : string.charAt(0);
5011
5012         var trailing = strSymbols
5013           ? castSlice(strSymbols, 1).join('')
5014           : string.slice(1);
5015
5016         return chr[methodName]() + trailing;
5017       };
5018     }
5019
5020     /**
5021      * Creates a function like `_.camelCase`.
5022      *
5023      * @private
5024      * @param {Function} callback The function to combine each word.
5025      * @returns {Function} Returns the new compounder function.
5026      */
5027     function createCompounder(callback) {
5028       return function(string) {
5029         return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5030       };
5031     }
5032
5033     /**
5034      * Creates a function that produces an instance of `Ctor` regardless of
5035      * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5036      *
5037      * @private
5038      * @param {Function} Ctor The constructor to wrap.
5039      * @returns {Function} Returns the new wrapped function.
5040      */
5041     function createCtor(Ctor) {
5042       return function() {
5043         // Use a `switch` statement to work with class constructors. See
5044         // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5045         // for more details.
5046         var args = arguments;
5047         switch (args.length) {
5048           case 0: return new Ctor;
5049           case 1: return new Ctor(args[0]);
5050           case 2: return new Ctor(args[0], args[1]);
5051           case 3: return new Ctor(args[0], args[1], args[2]);
5052           case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5053           case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5054           case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5055           case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5056         }
5057         var thisBinding = baseCreate(Ctor.prototype),
5058             result = Ctor.apply(thisBinding, args);
5059
5060         // Mimic the constructor's `return` behavior.
5061         // See https://es5.github.io/#x13.2.2 for more details.
5062         return isObject(result) ? result : thisBinding;
5063       };
5064     }
5065
5066     /**
5067      * Creates a function that wraps `func` to enable currying.
5068      *
5069      * @private
5070      * @param {Function} func The function to wrap.
5071      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5072      * @param {number} arity The arity of `func`.
5073      * @returns {Function} Returns the new wrapped function.
5074      */
5075     function createCurry(func, bitmask, arity) {
5076       var Ctor = createCtor(func);
5077
5078       function wrapper() {
5079         var length = arguments.length,
5080             args = Array(length),
5081             index = length,
5082             placeholder = getHolder(wrapper);
5083
5084         while (index--) {
5085           args[index] = arguments[index];
5086         }
5087         var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5088           ? []
5089           : replaceHolders(args, placeholder);
5090
5091         length -= holders.length;
5092         if (length < arity) {
5093           return createRecurry(
5094             func, bitmask, createHybrid, wrapper.placeholder, undefined,
5095             args, holders, undefined, undefined, arity - length);
5096         }
5097         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5098         return apply(fn, this, args);
5099       }
5100       return wrapper;
5101     }
5102
5103     /**
5104      * Creates a `_.find` or `_.findLast` function.
5105      *
5106      * @private
5107      * @param {Function} findIndexFunc The function to find the collection index.
5108      * @returns {Function} Returns the new find function.
5109      */
5110     function createFind(findIndexFunc) {
5111       return function(collection, predicate, fromIndex) {
5112         var iterable = Object(collection);
5113         if (!isArrayLike(collection)) {
5114           var iteratee = getIteratee(predicate, 3);
5115           collection = keys(collection);
5116           predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5117         }
5118         var index = findIndexFunc(collection, predicate, fromIndex);
5119         return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5120       };
5121     }
5122
5123     /**
5124      * Creates a `_.flow` or `_.flowRight` function.
5125      *
5126      * @private
5127      * @param {boolean} [fromRight] Specify iterating from right to left.
5128      * @returns {Function} Returns the new flow function.
5129      */
5130     function createFlow(fromRight) {
5131       return flatRest(function(funcs) {
5132         var length = funcs.length,
5133             index = length,
5134             prereq = LodashWrapper.prototype.thru;
5135
5136         if (fromRight) {
5137           funcs.reverse();
5138         }
5139         while (index--) {
5140           var func = funcs[index];
5141           if (typeof func != 'function') {
5142             throw new TypeError(FUNC_ERROR_TEXT);
5143           }
5144           if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5145             var wrapper = new LodashWrapper([], true);
5146           }
5147         }
5148         index = wrapper ? index : length;
5149         while (++index < length) {
5150           func = funcs[index];
5151
5152           var funcName = getFuncName(func),
5153               data = funcName == 'wrapper' ? getData(func) : undefined;
5154
5155           if (data && isLaziable(data[0]) &&
5156                 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5157                 !data[4].length && data[9] == 1
5158               ) {
5159             wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5160           } else {
5161             wrapper = (func.length == 1 && isLaziable(func))
5162               ? wrapper[funcName]()
5163               : wrapper.thru(func);
5164           }
5165         }
5166         return function() {
5167           var args = arguments,
5168               value = args[0];
5169
5170           if (wrapper && args.length == 1 && isArray(value)) {
5171             return wrapper.plant(value).value();
5172           }
5173           var index = 0,
5174               result = length ? funcs[index].apply(this, args) : value;
5175
5176           while (++index < length) {
5177             result = funcs[index].call(this, result);
5178           }
5179           return result;
5180         };
5181       });
5182     }
5183
5184     /**
5185      * Creates a function that wraps `func` to invoke it with optional `this`
5186      * binding of `thisArg`, partial application, and currying.
5187      *
5188      * @private
5189      * @param {Function|string} func The function or method name to wrap.
5190      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5191      * @param {*} [thisArg] The `this` binding of `func`.
5192      * @param {Array} [partials] The arguments to prepend to those provided to
5193      *  the new function.
5194      * @param {Array} [holders] The `partials` placeholder indexes.
5195      * @param {Array} [partialsRight] The arguments to append to those provided
5196      *  to the new function.
5197      * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5198      * @param {Array} [argPos] The argument positions of the new function.
5199      * @param {number} [ary] The arity cap of `func`.
5200      * @param {number} [arity] The arity of `func`.
5201      * @returns {Function} Returns the new wrapped function.
5202      */
5203     function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5204       var isAry = bitmask & WRAP_ARY_FLAG,
5205           isBind = bitmask & WRAP_BIND_FLAG,
5206           isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5207           isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5208           isFlip = bitmask & WRAP_FLIP_FLAG,
5209           Ctor = isBindKey ? undefined : createCtor(func);
5210
5211       function wrapper() {
5212         var length = arguments.length,
5213             args = Array(length),
5214             index = length;
5215
5216         while (index--) {
5217           args[index] = arguments[index];
5218         }
5219         if (isCurried) {
5220           var placeholder = getHolder(wrapper),
5221               holdersCount = countHolders(args, placeholder);
5222         }
5223         if (partials) {
5224           args = composeArgs(args, partials, holders, isCurried);
5225         }
5226         if (partialsRight) {
5227           args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5228         }
5229         length -= holdersCount;
5230         if (isCurried && length < arity) {
5231           var newHolders = replaceHolders(args, placeholder);
5232           return createRecurry(
5233             func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5234             args, newHolders, argPos, ary, arity - length
5235           );
5236         }
5237         var thisBinding = isBind ? thisArg : this,
5238             fn = isBindKey ? thisBinding[func] : func;
5239
5240         length = args.length;
5241         if (argPos) {
5242           args = reorder(args, argPos);
5243         } else if (isFlip && length > 1) {
5244           args.reverse();
5245         }
5246         if (isAry && ary < length) {
5247           args.length = ary;
5248         }
5249         if (this && this !== root && this instanceof wrapper) {
5250           fn = Ctor || createCtor(fn);
5251         }
5252         return fn.apply(thisBinding, args);
5253       }
5254       return wrapper;
5255     }
5256
5257     /**
5258      * Creates a function like `_.invertBy`.
5259      *
5260      * @private
5261      * @param {Function} setter The function to set accumulator values.
5262      * @param {Function} toIteratee The function to resolve iteratees.
5263      * @returns {Function} Returns the new inverter function.
5264      */
5265     function createInverter(setter, toIteratee) {
5266       return function(object, iteratee) {
5267         return baseInverter(object, setter, toIteratee(iteratee), {});
5268       };
5269     }
5270
5271     /**
5272      * Creates a function that performs a mathematical operation on two values.
5273      *
5274      * @private
5275      * @param {Function} operator The function to perform the operation.
5276      * @param {number} [defaultValue] The value used for `undefined` arguments.
5277      * @returns {Function} Returns the new mathematical operation function.
5278      */
5279     function createMathOperation(operator, defaultValue) {
5280       return function(value, other) {
5281         var result;
5282         if (value === undefined && other === undefined) {
5283           return defaultValue;
5284         }
5285         if (value !== undefined) {
5286           result = value;
5287         }
5288         if (other !== undefined) {
5289           if (result === undefined) {
5290             return other;
5291           }
5292           if (typeof value == 'string' || typeof other == 'string') {
5293             value = baseToString(value);
5294             other = baseToString(other);
5295           } else {
5296             value = baseToNumber(value);
5297             other = baseToNumber(other);
5298           }
5299           result = operator(value, other);
5300         }
5301         return result;
5302       };
5303     }
5304
5305     /**
5306      * Creates a function like `_.over`.
5307      *
5308      * @private
5309      * @param {Function} arrayFunc The function to iterate over iteratees.
5310      * @returns {Function} Returns the new over function.
5311      */
5312     function createOver(arrayFunc) {
5313       return flatRest(function(iteratees) {
5314         iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5315         return baseRest(function(args) {
5316           var thisArg = this;
5317           return arrayFunc(iteratees, function(iteratee) {
5318             return apply(iteratee, thisArg, args);
5319           });
5320         });
5321       });
5322     }
5323
5324     /**
5325      * Creates the padding for `string` based on `length`. The `chars` string
5326      * is truncated if the number of characters exceeds `length`.
5327      *
5328      * @private
5329      * @param {number} length The padding length.
5330      * @param {string} [chars=' '] The string used as padding.
5331      * @returns {string} Returns the padding for `string`.
5332      */
5333     function createPadding(length, chars) {
5334       chars = chars === undefined ? ' ' : baseToString(chars);
5335
5336       var charsLength = chars.length;
5337       if (charsLength < 2) {
5338         return charsLength ? baseRepeat(chars, length) : chars;
5339       }
5340       var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5341       return hasUnicode(chars)
5342         ? castSlice(stringToArray(result), 0, length).join('')
5343         : result.slice(0, length);
5344     }
5345
5346     /**
5347      * Creates a function that wraps `func` to invoke it with the `this` binding
5348      * of `thisArg` and `partials` prepended to the arguments it receives.
5349      *
5350      * @private
5351      * @param {Function} func The function to wrap.
5352      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5353      * @param {*} thisArg The `this` binding of `func`.
5354      * @param {Array} partials The arguments to prepend to those provided to
5355      *  the new function.
5356      * @returns {Function} Returns the new wrapped function.
5357      */
5358     function createPartial(func, bitmask, thisArg, partials) {
5359       var isBind = bitmask & WRAP_BIND_FLAG,
5360           Ctor = createCtor(func);
5361
5362       function wrapper() {
5363         var argsIndex = -1,
5364             argsLength = arguments.length,
5365             leftIndex = -1,
5366             leftLength = partials.length,
5367             args = Array(leftLength + argsLength),
5368             fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5369
5370         while (++leftIndex < leftLength) {
5371           args[leftIndex] = partials[leftIndex];
5372         }
5373         while (argsLength--) {
5374           args[leftIndex++] = arguments[++argsIndex];
5375         }
5376         return apply(fn, isBind ? thisArg : this, args);
5377       }
5378       return wrapper;
5379     }
5380
5381     /**
5382      * Creates a `_.range` or `_.rangeRight` function.
5383      *
5384      * @private
5385      * @param {boolean} [fromRight] Specify iterating from right to left.
5386      * @returns {Function} Returns the new range function.
5387      */
5388     function createRange(fromRight) {
5389       return function(start, end, step) {
5390         if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5391           end = step = undefined;
5392         }
5393         // Ensure the sign of `-0` is preserved.
5394         start = toFinite(start);
5395         if (end === undefined) {
5396           end = start;
5397           start = 0;
5398         } else {
5399           end = toFinite(end);
5400         }
5401         step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5402         return baseRange(start, end, step, fromRight);
5403       };
5404     }
5405
5406     /**
5407      * Creates a function that performs a relational operation on two values.
5408      *
5409      * @private
5410      * @param {Function} operator The function to perform the operation.
5411      * @returns {Function} Returns the new relational operation function.
5412      */
5413     function createRelationalOperation(operator) {
5414       return function(value, other) {
5415         if (!(typeof value == 'string' && typeof other == 'string')) {
5416           value = toNumber(value);
5417           other = toNumber(other);
5418         }
5419         return operator(value, other);
5420       };
5421     }
5422
5423     /**
5424      * Creates a function that wraps `func` to continue currying.
5425      *
5426      * @private
5427      * @param {Function} func The function to wrap.
5428      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5429      * @param {Function} wrapFunc The function to create the `func` wrapper.
5430      * @param {*} placeholder The placeholder value.
5431      * @param {*} [thisArg] The `this` binding of `func`.
5432      * @param {Array} [partials] The arguments to prepend to those provided to
5433      *  the new function.
5434      * @param {Array} [holders] The `partials` placeholder indexes.
5435      * @param {Array} [argPos] The argument positions of the new function.
5436      * @param {number} [ary] The arity cap of `func`.
5437      * @param {number} [arity] The arity of `func`.
5438      * @returns {Function} Returns the new wrapped function.
5439      */
5440     function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5441       var isCurry = bitmask & WRAP_CURRY_FLAG,
5442           newHolders = isCurry ? holders : undefined,
5443           newHoldersRight = isCurry ? undefined : holders,
5444           newPartials = isCurry ? partials : undefined,
5445           newPartialsRight = isCurry ? undefined : partials;
5446
5447       bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5448       bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5449
5450       if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5451         bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5452       }
5453       var newData = [
5454         func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5455         newHoldersRight, argPos, ary, arity
5456       ];
5457
5458       var result = wrapFunc.apply(undefined, newData);
5459       if (isLaziable(func)) {
5460         setData(result, newData);
5461       }
5462       result.placeholder = placeholder;
5463       return setWrapToString(result, func, bitmask);
5464     }
5465
5466     /**
5467      * Creates a function like `_.round`.
5468      *
5469      * @private
5470      * @param {string} methodName The name of the `Math` method to use when rounding.
5471      * @returns {Function} Returns the new round function.
5472      */
5473     function createRound(methodName) {
5474       var func = Math[methodName];
5475       return function(number, precision) {
5476         number = toNumber(number);
5477         precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
5478         if (precision) {
5479           // Shift with exponential notation to avoid floating-point issues.
5480           // See [MDN](https://mdn.io/round#Examples) for more details.
5481           var pair = (toString(number) + 'e').split('e'),
5482               value = func(pair[0] + 'e' + (+pair[1] + precision));
5483
5484           pair = (toString(value) + 'e').split('e');
5485           return +(pair[0] + 'e' + (+pair[1] - precision));
5486         }
5487         return func(number);
5488       };
5489     }
5490
5491     /**
5492      * Creates a set object of `values`.
5493      *
5494      * @private
5495      * @param {Array} values The values to add to the set.
5496      * @returns {Object} Returns the new set.
5497      */
5498     var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5499       return new Set(values);
5500     };
5501
5502     /**
5503      * Creates a `_.toPairs` or `_.toPairsIn` function.
5504      *
5505      * @private
5506      * @param {Function} keysFunc The function to get the keys of a given object.
5507      * @returns {Function} Returns the new pairs function.
5508      */
5509     function createToPairs(keysFunc) {
5510       return function(object) {
5511         var tag = getTag(object);
5512         if (tag == mapTag) {
5513           return mapToArray(object);
5514         }
5515         if (tag == setTag) {
5516           return setToPairs(object);
5517         }
5518         return baseToPairs(object, keysFunc(object));
5519       };
5520     }
5521
5522     /**
5523      * Creates a function that either curries or invokes `func` with optional
5524      * `this` binding and partially applied arguments.
5525      *
5526      * @private
5527      * @param {Function|string} func The function or method name to wrap.
5528      * @param {number} bitmask The bitmask flags.
5529      *    1 - `_.bind`
5530      *    2 - `_.bindKey`
5531      *    4 - `_.curry` or `_.curryRight` of a bound function
5532      *    8 - `_.curry`
5533      *   16 - `_.curryRight`
5534      *   32 - `_.partial`
5535      *   64 - `_.partialRight`
5536      *  128 - `_.rearg`
5537      *  256 - `_.ary`
5538      *  512 - `_.flip`
5539      * @param {*} [thisArg] The `this` binding of `func`.
5540      * @param {Array} [partials] The arguments to be partially applied.
5541      * @param {Array} [holders] The `partials` placeholder indexes.
5542      * @param {Array} [argPos] The argument positions of the new function.
5543      * @param {number} [ary] The arity cap of `func`.
5544      * @param {number} [arity] The arity of `func`.
5545      * @returns {Function} Returns the new wrapped function.
5546      */
5547     function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5548       var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5549       if (!isBindKey && typeof func != 'function') {
5550         throw new TypeError(FUNC_ERROR_TEXT);
5551       }
5552       var length = partials ? partials.length : 0;
5553       if (!length) {
5554         bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5555         partials = holders = undefined;
5556       }
5557       ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5558       arity = arity === undefined ? arity : toInteger(arity);
5559       length -= holders ? holders.length : 0;
5560
5561       if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5562         var partialsRight = partials,
5563             holdersRight = holders;
5564
5565         partials = holders = undefined;
5566       }
5567       var data = isBindKey ? undefined : getData(func);
5568
5569       var newData = [
5570         func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5571         argPos, ary, arity
5572       ];
5573
5574       if (data) {
5575         mergeData(newData, data);
5576       }
5577       func = newData[0];
5578       bitmask = newData[1];
5579       thisArg = newData[2];
5580       partials = newData[3];
5581       holders = newData[4];
5582       arity = newData[9] = newData[9] === undefined
5583         ? (isBindKey ? 0 : func.length)
5584         : nativeMax(newData[9] - length, 0);
5585
5586       if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5587         bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5588       }
5589       if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5590         var result = createBind(func, bitmask, thisArg);
5591       } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5592         result = createCurry(func, bitmask, arity);
5593       } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5594         result = createPartial(func, bitmask, thisArg, partials);
5595       } else {
5596         result = createHybrid.apply(undefined, newData);
5597       }
5598       var setter = data ? baseSetData : setData;
5599       return setWrapToString(setter(result, newData), func, bitmask);
5600     }
5601
5602     /**
5603      * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
5604      * of source objects to the destination object for all destination properties
5605      * that resolve to `undefined`.
5606      *
5607      * @private
5608      * @param {*} objValue The destination value.
5609      * @param {*} srcValue The source value.
5610      * @param {string} key The key of the property to assign.
5611      * @param {Object} object The parent object of `objValue`.
5612      * @returns {*} Returns the value to assign.
5613      */
5614     function customDefaultsAssignIn(objValue, srcValue, key, object) {
5615       if (objValue === undefined ||
5616           (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
5617         return srcValue;
5618       }
5619       return objValue;
5620     }
5621
5622     /**
5623      * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
5624      * objects into destination objects that are passed thru.
5625      *
5626      * @private
5627      * @param {*} objValue The destination value.
5628      * @param {*} srcValue The source value.
5629      * @param {string} key The key of the property to merge.
5630      * @param {Object} object The parent object of `objValue`.
5631      * @param {Object} source The parent object of `srcValue`.
5632      * @param {Object} [stack] Tracks traversed source values and their merged
5633      *  counterparts.
5634      * @returns {*} Returns the value to assign.
5635      */
5636     function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
5637       if (isObject(objValue) && isObject(srcValue)) {
5638         // Recursively merge objects and arrays (susceptible to call stack limits).
5639         stack.set(srcValue, objValue);
5640         baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
5641         stack['delete'](srcValue);
5642       }
5643       return objValue;
5644     }
5645
5646     /**
5647      * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
5648      * objects.
5649      *
5650      * @private
5651      * @param {*} value The value to inspect.
5652      * @param {string} key The key of the property to inspect.
5653      * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
5654      */
5655     function customOmitClone(value) {
5656       return isPlainObject(value) ? undefined : value;
5657     }
5658
5659     /**
5660      * A specialized version of `baseIsEqualDeep` for arrays with support for
5661      * partial deep comparisons.
5662      *
5663      * @private
5664      * @param {Array} array The array to compare.
5665      * @param {Array} other The other array to compare.
5666      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5667      * @param {Function} customizer The function to customize comparisons.
5668      * @param {Function} equalFunc The function to determine equivalents of values.
5669      * @param {Object} stack Tracks traversed `array` and `other` objects.
5670      * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5671      */
5672     function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5673       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5674           arrLength = array.length,
5675           othLength = other.length;
5676
5677       if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5678         return false;
5679       }
5680       // Assume cyclic values are equal.
5681       var stacked = stack.get(array);
5682       if (stacked && stack.get(other)) {
5683         return stacked == other;
5684       }
5685       var index = -1,
5686           result = true,
5687           seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5688
5689       stack.set(array, other);
5690       stack.set(other, array);
5691
5692       // Ignore non-index properties.
5693       while (++index < arrLength) {
5694         var arrValue = array[index],
5695             othValue = other[index];
5696
5697         if (customizer) {
5698           var compared = isPartial
5699             ? customizer(othValue, arrValue, index, other, array, stack)
5700             : customizer(arrValue, othValue, index, array, other, stack);
5701         }
5702         if (compared !== undefined) {
5703           if (compared) {
5704             continue;
5705           }
5706           result = false;
5707           break;
5708         }
5709         // Recursively compare arrays (susceptible to call stack limits).
5710         if (seen) {
5711           if (!arraySome(other, function(othValue, othIndex) {
5712                 if (!cacheHas(seen, othIndex) &&
5713                     (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5714                   return seen.push(othIndex);
5715                 }
5716               })) {
5717             result = false;
5718             break;
5719           }
5720         } else if (!(
5721               arrValue === othValue ||
5722                 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5723             )) {
5724           result = false;
5725           break;
5726         }
5727       }
5728       stack['delete'](array);
5729       stack['delete'](other);
5730       return result;
5731     }
5732
5733     /**
5734      * A specialized version of `baseIsEqualDeep` for comparing objects of
5735      * the same `toStringTag`.
5736      *
5737      * **Note:** This function only supports comparing values with tags of
5738      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5739      *
5740      * @private
5741      * @param {Object} object The object to compare.
5742      * @param {Object} other The other object to compare.
5743      * @param {string} tag The `toStringTag` of the objects to compare.
5744      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5745      * @param {Function} customizer The function to customize comparisons.
5746      * @param {Function} equalFunc The function to determine equivalents of values.
5747      * @param {Object} stack Tracks traversed `object` and `other` objects.
5748      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5749      */
5750     function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5751       switch (tag) {
5752         case dataViewTag:
5753           if ((object.byteLength != other.byteLength) ||
5754               (object.byteOffset != other.byteOffset)) {
5755             return false;
5756           }
5757           object = object.buffer;
5758           other = other.buffer;
5759
5760         case arrayBufferTag:
5761           if ((object.byteLength != other.byteLength) ||
5762               !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5763             return false;
5764           }
5765           return true;
5766
5767         case boolTag:
5768         case dateTag:
5769         case numberTag:
5770           // Coerce booleans to `1` or `0` and dates to milliseconds.
5771           // Invalid dates are coerced to `NaN`.
5772           return eq(+object, +other);
5773
5774         case errorTag:
5775           return object.name == other.name && object.message == other.message;
5776
5777         case regexpTag:
5778         case stringTag:
5779           // Coerce regexes to strings and treat strings, primitives and objects,
5780           // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5781           // for more details.
5782           return object == (other + '');
5783
5784         case mapTag:
5785           var convert = mapToArray;
5786
5787         case setTag:
5788           var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5789           convert || (convert = setToArray);
5790
5791           if (object.size != other.size && !isPartial) {
5792             return false;
5793           }
5794           // Assume cyclic values are equal.
5795           var stacked = stack.get(object);
5796           if (stacked) {
5797             return stacked == other;
5798           }
5799           bitmask |= COMPARE_UNORDERED_FLAG;
5800
5801           // Recursively compare objects (susceptible to call stack limits).
5802           stack.set(object, other);
5803           var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5804           stack['delete'](object);
5805           return result;
5806
5807         case symbolTag:
5808           if (symbolValueOf) {
5809             return symbolValueOf.call(object) == symbolValueOf.call(other);
5810           }
5811       }
5812       return false;
5813     }
5814
5815     /**
5816      * A specialized version of `baseIsEqualDeep` for objects with support for
5817      * partial deep comparisons.
5818      *
5819      * @private
5820      * @param {Object} object The object to compare.
5821      * @param {Object} other The other object to compare.
5822      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5823      * @param {Function} customizer The function to customize comparisons.
5824      * @param {Function} equalFunc The function to determine equivalents of values.
5825      * @param {Object} stack Tracks traversed `object` and `other` objects.
5826      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5827      */
5828     function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5829       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5830           objProps = getAllKeys(object),
5831           objLength = objProps.length,
5832           othProps = getAllKeys(other),
5833           othLength = othProps.length;
5834
5835       if (objLength != othLength && !isPartial) {
5836         return false;
5837       }
5838       var index = objLength;
5839       while (index--) {
5840         var key = objProps[index];
5841         if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5842           return false;
5843         }
5844       }
5845       // Assume cyclic values are equal.
5846       var stacked = stack.get(object);
5847       if (stacked && stack.get(other)) {
5848         return stacked == other;
5849       }
5850       var result = true;
5851       stack.set(object, other);
5852       stack.set(other, object);
5853
5854       var skipCtor = isPartial;
5855       while (++index < objLength) {
5856         key = objProps[index];
5857         var objValue = object[key],
5858             othValue = other[key];
5859
5860         if (customizer) {
5861           var compared = isPartial
5862             ? customizer(othValue, objValue, key, other, object, stack)
5863             : customizer(objValue, othValue, key, object, other, stack);
5864         }
5865         // Recursively compare objects (susceptible to call stack limits).
5866         if (!(compared === undefined
5867               ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5868               : compared
5869             )) {
5870           result = false;
5871           break;
5872         }
5873         skipCtor || (skipCtor = key == 'constructor');
5874       }
5875       if (result && !skipCtor) {
5876         var objCtor = object.constructor,
5877             othCtor = other.constructor;
5878
5879         // Non `Object` object instances with different constructors are not equal.
5880         if (objCtor != othCtor &&
5881             ('constructor' in object && 'constructor' in other) &&
5882             !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5883               typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5884           result = false;
5885         }
5886       }
5887       stack['delete'](object);
5888       stack['delete'](other);
5889       return result;
5890     }
5891
5892     /**
5893      * A specialized version of `baseRest` which flattens the rest array.
5894      *
5895      * @private
5896      * @param {Function} func The function to apply a rest parameter to.
5897      * @returns {Function} Returns the new function.
5898      */
5899     function flatRest(func) {
5900       return setToString(overRest(func, undefined, flatten), func + '');
5901     }
5902
5903     /**
5904      * Creates an array of own enumerable property names and symbols of `object`.
5905      *
5906      * @private
5907      * @param {Object} object The object to query.
5908      * @returns {Array} Returns the array of property names and symbols.
5909      */
5910     function getAllKeys(object) {
5911       return baseGetAllKeys(object, keys, getSymbols);
5912     }
5913
5914     /**
5915      * Creates an array of own and inherited enumerable property names and
5916      * symbols of `object`.
5917      *
5918      * @private
5919      * @param {Object} object The object to query.
5920      * @returns {Array} Returns the array of property names and symbols.
5921      */
5922     function getAllKeysIn(object) {
5923       return baseGetAllKeys(object, keysIn, getSymbolsIn);
5924     }
5925
5926     /**
5927      * Gets metadata for `func`.
5928      *
5929      * @private
5930      * @param {Function} func The function to query.
5931      * @returns {*} Returns the metadata for `func`.
5932      */
5933     var getData = !metaMap ? noop : function(func) {
5934       return metaMap.get(func);
5935     };
5936
5937     /**
5938      * Gets the name of `func`.
5939      *
5940      * @private
5941      * @param {Function} func The function to query.
5942      * @returns {string} Returns the function name.
5943      */
5944     function getFuncName(func) {
5945       var result = (func.name + ''),
5946           array = realNames[result],
5947           length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5948
5949       while (length--) {
5950         var data = array[length],
5951             otherFunc = data.func;
5952         if (otherFunc == null || otherFunc == func) {
5953           return data.name;
5954         }
5955       }
5956       return result;
5957     }
5958
5959     /**
5960      * Gets the argument placeholder value for `func`.
5961      *
5962      * @private
5963      * @param {Function} func The function to inspect.
5964      * @returns {*} Returns the placeholder value.
5965      */
5966     function getHolder(func) {
5967       var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5968       return object.placeholder;
5969     }
5970
5971     /**
5972      * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5973      * this function returns the custom method, otherwise it returns `baseIteratee`.
5974      * If arguments are provided, the chosen function is invoked with them and
5975      * its result is returned.
5976      *
5977      * @private
5978      * @param {*} [value] The value to convert to an iteratee.
5979      * @param {number} [arity] The arity of the created iteratee.
5980      * @returns {Function} Returns the chosen function or its result.
5981      */
5982     function getIteratee() {
5983       var result = lodash.iteratee || iteratee;
5984       result = result === iteratee ? baseIteratee : result;
5985       return arguments.length ? result(arguments[0], arguments[1]) : result;
5986     }
5987
5988     /**
5989      * Gets the data for `map`.
5990      *
5991      * @private
5992      * @param {Object} map The map to query.
5993      * @param {string} key The reference key.
5994      * @returns {*} Returns the map data.
5995      */
5996     function getMapData(map, key) {
5997       var data = map.__data__;
5998       return isKeyable(key)
5999         ? data[typeof key == 'string' ? 'string' : 'hash']
6000         : data.map;
6001     }
6002
6003     /**
6004      * Gets the property names, values, and compare flags of `object`.
6005      *
6006      * @private
6007      * @param {Object} object The object to query.
6008      * @returns {Array} Returns the match data of `object`.
6009      */
6010     function getMatchData(object) {
6011       var result = keys(object),
6012           length = result.length;
6013
6014       while (length--) {
6015         var key = result[length],
6016             value = object[key];
6017
6018         result[length] = [key, value, isStrictComparable(value)];
6019       }
6020       return result;
6021     }
6022
6023     /**
6024      * Gets the native function at `key` of `object`.
6025      *
6026      * @private
6027      * @param {Object} object The object to query.
6028      * @param {string} key The key of the method to get.
6029      * @returns {*} Returns the function if it's native, else `undefined`.
6030      */
6031     function getNative(object, key) {
6032       var value = getValue(object, key);
6033       return baseIsNative(value) ? value : undefined;
6034     }
6035
6036     /**
6037      * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6038      *
6039      * @private
6040      * @param {*} value The value to query.
6041      * @returns {string} Returns the raw `toStringTag`.
6042      */
6043     function getRawTag(value) {
6044       var isOwn = hasOwnProperty.call(value, symToStringTag),
6045           tag = value[symToStringTag];
6046
6047       try {
6048         value[symToStringTag] = undefined;
6049         var unmasked = true;
6050       } catch (e) {}
6051
6052       var result = nativeObjectToString.call(value);
6053       if (unmasked) {
6054         if (isOwn) {
6055           value[symToStringTag] = tag;
6056         } else {
6057           delete value[symToStringTag];
6058         }
6059       }
6060       return result;
6061     }
6062
6063     /**
6064      * Creates an array of the own enumerable symbols of `object`.
6065      *
6066      * @private
6067      * @param {Object} object The object to query.
6068      * @returns {Array} Returns the array of symbols.
6069      */
6070     var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
6071       if (object == null) {
6072         return [];
6073       }
6074       object = Object(object);
6075       return arrayFilter(nativeGetSymbols(object), function(symbol) {
6076         return propertyIsEnumerable.call(object, symbol);
6077       });
6078     };
6079
6080     /**
6081      * Creates an array of the own and inherited enumerable symbols of `object`.
6082      *
6083      * @private
6084      * @param {Object} object The object to query.
6085      * @returns {Array} Returns the array of symbols.
6086      */
6087     var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6088       var result = [];
6089       while (object) {
6090         arrayPush(result, getSymbols(object));
6091         object = getPrototype(object);
6092       }
6093       return result;
6094     };
6095
6096     /**
6097      * Gets the `toStringTag` of `value`.
6098      *
6099      * @private
6100      * @param {*} value The value to query.
6101      * @returns {string} Returns the `toStringTag`.
6102      */
6103     var getTag = baseGetTag;
6104
6105     // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6106     if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6107         (Map && getTag(new Map) != mapTag) ||
6108         (Promise && getTag(Promise.resolve()) != promiseTag) ||
6109         (Set && getTag(new Set) != setTag) ||
6110         (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6111       getTag = function(value) {
6112         var result = baseGetTag(value),
6113             Ctor = result == objectTag ? value.constructor : undefined,
6114             ctorString = Ctor ? toSource(Ctor) : '';
6115
6116         if (ctorString) {
6117           switch (ctorString) {
6118             case dataViewCtorString: return dataViewTag;
6119             case mapCtorString: return mapTag;
6120             case promiseCtorString: return promiseTag;
6121             case setCtorString: return setTag;
6122             case weakMapCtorString: return weakMapTag;
6123           }
6124         }
6125         return result;
6126       };
6127     }
6128
6129     /**
6130      * Gets the view, applying any `transforms` to the `start` and `end` positions.
6131      *
6132      * @private
6133      * @param {number} start The start of the view.
6134      * @param {number} end The end of the view.
6135      * @param {Array} transforms The transformations to apply to the view.
6136      * @returns {Object} Returns an object containing the `start` and `end`
6137      *  positions of the view.
6138      */
6139     function getView(start, end, transforms) {
6140       var index = -1,
6141           length = transforms.length;
6142
6143       while (++index < length) {
6144         var data = transforms[index],
6145             size = data.size;
6146
6147         switch (data.type) {
6148           case 'drop':      start += size; break;
6149           case 'dropRight': end -= size; break;
6150           case 'take':      end = nativeMin(end, start + size); break;
6151           case 'takeRight': start = nativeMax(start, end - size); break;
6152         }
6153       }
6154       return { 'start': start, 'end': end };
6155     }
6156
6157     /**
6158      * Extracts wrapper details from the `source` body comment.
6159      *
6160      * @private
6161      * @param {string} source The source to inspect.
6162      * @returns {Array} Returns the wrapper details.
6163      */
6164     function getWrapDetails(source) {
6165       var match = source.match(reWrapDetails);
6166       return match ? match[1].split(reSplitDetails) : [];
6167     }
6168
6169     /**
6170      * Checks if `path` exists on `object`.
6171      *
6172      * @private
6173      * @param {Object} object The object to query.
6174      * @param {Array|string} path The path to check.
6175      * @param {Function} hasFunc The function to check properties.
6176      * @returns {boolean} Returns `true` if `path` exists, else `false`.
6177      */
6178     function hasPath(object, path, hasFunc) {
6179       path = castPath(path, object);
6180
6181       var index = -1,
6182           length = path.length,
6183           result = false;
6184
6185       while (++index < length) {
6186         var key = toKey(path[index]);
6187         if (!(result = object != null && hasFunc(object, key))) {
6188           break;
6189         }
6190         object = object[key];
6191       }
6192       if (result || ++index != length) {
6193         return result;
6194       }
6195       length = object == null ? 0 : object.length;
6196       return !!length && isLength(length) && isIndex(key, length) &&
6197         (isArray(object) || isArguments(object));
6198     }
6199
6200     /**
6201      * Initializes an array clone.
6202      *
6203      * @private
6204      * @param {Array} array The array to clone.
6205      * @returns {Array} Returns the initialized clone.
6206      */
6207     function initCloneArray(array) {
6208       var length = array.length,
6209           result = array.constructor(length);
6210
6211       // Add properties assigned by `RegExp#exec`.
6212       if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6213         result.index = array.index;
6214         result.input = array.input;
6215       }
6216       return result;
6217     }
6218
6219     /**
6220      * Initializes an object clone.
6221      *
6222      * @private
6223      * @param {Object} object The object to clone.
6224      * @returns {Object} Returns the initialized clone.
6225      */
6226     function initCloneObject(object) {
6227       return (typeof object.constructor == 'function' && !isPrototype(object))
6228         ? baseCreate(getPrototype(object))
6229         : {};
6230     }
6231
6232     /**
6233      * Initializes an object clone based on its `toStringTag`.
6234      *
6235      * **Note:** This function only supports cloning values with tags of
6236      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6237      *
6238      * @private
6239      * @param {Object} object The object to clone.
6240      * @param {string} tag The `toStringTag` of the object to clone.
6241      * @param {Function} cloneFunc The function to clone values.
6242      * @param {boolean} [isDeep] Specify a deep clone.
6243      * @returns {Object} Returns the initialized clone.
6244      */
6245     function initCloneByTag(object, tag, cloneFunc, isDeep) {
6246       var Ctor = object.constructor;
6247       switch (tag) {
6248         case arrayBufferTag:
6249           return cloneArrayBuffer(object);
6250
6251         case boolTag:
6252         case dateTag:
6253           return new Ctor(+object);
6254
6255         case dataViewTag:
6256           return cloneDataView(object, isDeep);
6257
6258         case float32Tag: case float64Tag:
6259         case int8Tag: case int16Tag: case int32Tag:
6260         case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6261           return cloneTypedArray(object, isDeep);
6262
6263         case mapTag:
6264           return cloneMap(object, isDeep, cloneFunc);
6265
6266         case numberTag:
6267         case stringTag:
6268           return new Ctor(object);
6269
6270         case regexpTag:
6271           return cloneRegExp(object);
6272
6273         case setTag:
6274           return cloneSet(object, isDeep, cloneFunc);
6275
6276         case symbolTag:
6277           return cloneSymbol(object);
6278       }
6279     }
6280
6281     /**
6282      * Inserts wrapper `details` in a comment at the top of the `source` body.
6283      *
6284      * @private
6285      * @param {string} source The source to modify.
6286      * @returns {Array} details The details to insert.
6287      * @returns {string} Returns the modified source.
6288      */
6289     function insertWrapDetails(source, details) {
6290       var length = details.length;
6291       if (!length) {
6292         return source;
6293       }
6294       var lastIndex = length - 1;
6295       details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6296       details = details.join(length > 2 ? ', ' : ' ');
6297       return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6298     }
6299
6300     /**
6301      * Checks if `value` is a flattenable `arguments` object or array.
6302      *
6303      * @private
6304      * @param {*} value The value to check.
6305      * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6306      */
6307     function isFlattenable(value) {
6308       return isArray(value) || isArguments(value) ||
6309         !!(spreadableSymbol && value && value[spreadableSymbol]);
6310     }
6311
6312     /**
6313      * Checks if `value` is a valid array-like index.
6314      *
6315      * @private
6316      * @param {*} value The value to check.
6317      * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6318      * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6319      */
6320     function isIndex(value, length) {
6321       length = length == null ? MAX_SAFE_INTEGER : length;
6322       return !!length &&
6323         (typeof value == 'number' || reIsUint.test(value)) &&
6324         (value > -1 && value % 1 == 0 && value < length);
6325     }
6326
6327     /**
6328      * Checks if the given arguments are from an iteratee call.
6329      *
6330      * @private
6331      * @param {*} value The potential iteratee value argument.
6332      * @param {*} index The potential iteratee index or key argument.
6333      * @param {*} object The potential iteratee object argument.
6334      * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6335      *  else `false`.
6336      */
6337     function isIterateeCall(value, index, object) {
6338       if (!isObject(object)) {
6339         return false;
6340       }
6341       var type = typeof index;
6342       if (type == 'number'
6343             ? (isArrayLike(object) && isIndex(index, object.length))
6344             : (type == 'string' && index in object)
6345           ) {
6346         return eq(object[index], value);
6347       }
6348       return false;
6349     }
6350
6351     /**
6352      * Checks if `value` is a property name and not a property path.
6353      *
6354      * @private
6355      * @param {*} value The value to check.
6356      * @param {Object} [object] The object to query keys on.
6357      * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6358      */
6359     function isKey(value, object) {
6360       if (isArray(value)) {
6361         return false;
6362       }
6363       var type = typeof value;
6364       if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6365           value == null || isSymbol(value)) {
6366         return true;
6367       }
6368       return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6369         (object != null && value in Object(object));
6370     }
6371
6372     /**
6373      * Checks if `value` is suitable for use as unique object key.
6374      *
6375      * @private
6376      * @param {*} value The value to check.
6377      * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6378      */
6379     function isKeyable(value) {
6380       var type = typeof value;
6381       return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6382         ? (value !== '__proto__')
6383         : (value === null);
6384     }
6385
6386     /**
6387      * Checks if `func` has a lazy counterpart.
6388      *
6389      * @private
6390      * @param {Function} func The function to check.
6391      * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6392      *  else `false`.
6393      */
6394     function isLaziable(func) {
6395       var funcName = getFuncName(func),
6396           other = lodash[funcName];
6397
6398       if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6399         return false;
6400       }
6401       if (func === other) {
6402         return true;
6403       }
6404       var data = getData(other);
6405       return !!data && func === data[0];
6406     }
6407
6408     /**
6409      * Checks if `func` has its source masked.
6410      *
6411      * @private
6412      * @param {Function} func The function to check.
6413      * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6414      */
6415     function isMasked(func) {
6416       return !!maskSrcKey && (maskSrcKey in func);
6417     }
6418
6419     /**
6420      * Checks if `func` is capable of being masked.
6421      *
6422      * @private
6423      * @param {*} value The value to check.
6424      * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6425      */
6426     var isMaskable = coreJsData ? isFunction : stubFalse;
6427
6428     /**
6429      * Checks if `value` is likely a prototype object.
6430      *
6431      * @private
6432      * @param {*} value The value to check.
6433      * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6434      */
6435     function isPrototype(value) {
6436       var Ctor = value && value.constructor,
6437           proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6438
6439       return value === proto;
6440     }
6441
6442     /**
6443      * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6444      *
6445      * @private
6446      * @param {*} value The value to check.
6447      * @returns {boolean} Returns `true` if `value` if suitable for strict
6448      *  equality comparisons, else `false`.
6449      */
6450     function isStrictComparable(value) {
6451       return value === value && !isObject(value);
6452     }
6453
6454     /**
6455      * A specialized version of `matchesProperty` for source values suitable
6456      * for strict equality comparisons, i.e. `===`.
6457      *
6458      * @private
6459      * @param {string} key The key of the property to get.
6460      * @param {*} srcValue The value to match.
6461      * @returns {Function} Returns the new spec function.
6462      */
6463     function matchesStrictComparable(key, srcValue) {
6464       return function(object) {
6465         if (object == null) {
6466           return false;
6467         }
6468         return object[key] === srcValue &&
6469           (srcValue !== undefined || (key in Object(object)));
6470       };
6471     }
6472
6473     /**
6474      * A specialized version of `_.memoize` which clears the memoized function's
6475      * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6476      *
6477      * @private
6478      * @param {Function} func The function to have its output memoized.
6479      * @returns {Function} Returns the new memoized function.
6480      */
6481     function memoizeCapped(func) {
6482       var result = memoize(func, function(key) {
6483         if (cache.size === MAX_MEMOIZE_SIZE) {
6484           cache.clear();
6485         }
6486         return key;
6487       });
6488
6489       var cache = result.cache;
6490       return result;
6491     }
6492
6493     /**
6494      * Merges the function metadata of `source` into `data`.
6495      *
6496      * Merging metadata reduces the number of wrappers used to invoke a function.
6497      * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6498      * may be applied regardless of execution order. Methods like `_.ary` and
6499      * `_.rearg` modify function arguments, making the order in which they are
6500      * executed important, preventing the merging of metadata. However, we make
6501      * an exception for a safe combined case where curried functions have `_.ary`
6502      * and or `_.rearg` applied.
6503      *
6504      * @private
6505      * @param {Array} data The destination metadata.
6506      * @param {Array} source The source metadata.
6507      * @returns {Array} Returns `data`.
6508      */
6509     function mergeData(data, source) {
6510       var bitmask = data[1],
6511           srcBitmask = source[1],
6512           newBitmask = bitmask | srcBitmask,
6513           isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6514
6515       var isCombo =
6516         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6517         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6518         ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6519
6520       // Exit early if metadata can't be merged.
6521       if (!(isCommon || isCombo)) {
6522         return data;
6523       }
6524       // Use source `thisArg` if available.
6525       if (srcBitmask & WRAP_BIND_FLAG) {
6526         data[2] = source[2];
6527         // Set when currying a bound function.
6528         newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6529       }
6530       // Compose partial arguments.
6531       var value = source[3];
6532       if (value) {
6533         var partials = data[3];
6534         data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6535         data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6536       }
6537       // Compose partial right arguments.
6538       value = source[5];
6539       if (value) {
6540         partials = data[5];
6541         data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6542         data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6543       }
6544       // Use source `argPos` if available.
6545       value = source[7];
6546       if (value) {
6547         data[7] = value;
6548       }
6549       // Use source `ary` if it's smaller.
6550       if (srcBitmask & WRAP_ARY_FLAG) {
6551         data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6552       }
6553       // Use source `arity` if one is not provided.
6554       if (data[9] == null) {
6555         data[9] = source[9];
6556       }
6557       // Use source `func` and merge bitmasks.
6558       data[0] = source[0];
6559       data[1] = newBitmask;
6560
6561       return data;
6562     }
6563
6564     /**
6565      * This function is like
6566      * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6567      * except that it includes inherited enumerable properties.
6568      *
6569      * @private
6570      * @param {Object} object The object to query.
6571      * @returns {Array} Returns the array of property names.
6572      */
6573     function nativeKeysIn(object) {
6574       var result = [];
6575       if (object != null) {
6576         for (var key in Object(object)) {
6577           result.push(key);
6578         }
6579       }
6580       return result;
6581     }
6582
6583     /**
6584      * Converts `value` to a string using `Object.prototype.toString`.
6585      *
6586      * @private
6587      * @param {*} value The value to convert.
6588      * @returns {string} Returns the converted string.
6589      */
6590     function objectToString(value) {
6591       return nativeObjectToString.call(value);
6592     }
6593
6594     /**
6595      * A specialized version of `baseRest` which transforms the rest array.
6596      *
6597      * @private
6598      * @param {Function} func The function to apply a rest parameter to.
6599      * @param {number} [start=func.length-1] The start position of the rest parameter.
6600      * @param {Function} transform The rest array transform.
6601      * @returns {Function} Returns the new function.
6602      */
6603     function overRest(func, start, transform) {
6604       start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6605       return function() {
6606         var args = arguments,
6607             index = -1,
6608             length = nativeMax(args.length - start, 0),
6609             array = Array(length);
6610
6611         while (++index < length) {
6612           array[index] = args[start + index];
6613         }
6614         index = -1;
6615         var otherArgs = Array(start + 1);
6616         while (++index < start) {
6617           otherArgs[index] = args[index];
6618         }
6619         otherArgs[start] = transform(array);
6620         return apply(func, this, otherArgs);
6621       };
6622     }
6623
6624     /**
6625      * Gets the parent value at `path` of `object`.
6626      *
6627      * @private
6628      * @param {Object} object The object to query.
6629      * @param {Array} path The path to get the parent value of.
6630      * @returns {*} Returns the parent value.
6631      */
6632     function parent(object, path) {
6633       return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
6634     }
6635
6636     /**
6637      * Reorder `array` according to the specified indexes where the element at
6638      * the first index is assigned as the first element, the element at
6639      * the second index is assigned as the second element, and so on.
6640      *
6641      * @private
6642      * @param {Array} array The array to reorder.
6643      * @param {Array} indexes The arranged array indexes.
6644      * @returns {Array} Returns `array`.
6645      */
6646     function reorder(array, indexes) {
6647       var arrLength = array.length,
6648           length = nativeMin(indexes.length, arrLength),
6649           oldArray = copyArray(array);
6650
6651       while (length--) {
6652         var index = indexes[length];
6653         array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6654       }
6655       return array;
6656     }
6657
6658     /**
6659      * Sets metadata for `func`.
6660      *
6661      * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6662      * period of time, it will trip its breaker and transition to an identity
6663      * function to avoid garbage collection pauses in V8. See
6664      * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6665      * for more details.
6666      *
6667      * @private
6668      * @param {Function} func The function to associate metadata with.
6669      * @param {*} data The metadata.
6670      * @returns {Function} Returns `func`.
6671      */
6672     var setData = shortOut(baseSetData);
6673
6674     /**
6675      * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6676      *
6677      * @private
6678      * @param {Function} func The function to delay.
6679      * @param {number} wait The number of milliseconds to delay invocation.
6680      * @returns {number|Object} Returns the timer id or timeout object.
6681      */
6682     var setTimeout = ctxSetTimeout || function(func, wait) {
6683       return root.setTimeout(func, wait);
6684     };
6685
6686     /**
6687      * Sets the `toString` method of `func` to return `string`.
6688      *
6689      * @private
6690      * @param {Function} func The function to modify.
6691      * @param {Function} string The `toString` result.
6692      * @returns {Function} Returns `func`.
6693      */
6694     var setToString = shortOut(baseSetToString);
6695
6696     /**
6697      * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6698      * with wrapper details in a comment at the top of the source body.
6699      *
6700      * @private
6701      * @param {Function} wrapper The function to modify.
6702      * @param {Function} reference The reference function.
6703      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6704      * @returns {Function} Returns `wrapper`.
6705      */
6706     function setWrapToString(wrapper, reference, bitmask) {
6707       var source = (reference + '');
6708       return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6709     }
6710
6711     /**
6712      * Creates a function that'll short out and invoke `identity` instead
6713      * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6714      * milliseconds.
6715      *
6716      * @private
6717      * @param {Function} func The function to restrict.
6718      * @returns {Function} Returns the new shortable function.
6719      */
6720     function shortOut(func) {
6721       var count = 0,
6722           lastCalled = 0;
6723
6724       return function() {
6725         var stamp = nativeNow(),
6726             remaining = HOT_SPAN - (stamp - lastCalled);
6727
6728         lastCalled = stamp;
6729         if (remaining > 0) {
6730           if (++count >= HOT_COUNT) {
6731             return arguments[0];
6732           }
6733         } else {
6734           count = 0;
6735         }
6736         return func.apply(undefined, arguments);
6737       };
6738     }
6739
6740     /**
6741      * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6742      *
6743      * @private
6744      * @param {Array} array The array to shuffle.
6745      * @param {number} [size=array.length] The size of `array`.
6746      * @returns {Array} Returns `array`.
6747      */
6748     function shuffleSelf(array, size) {
6749       var index = -1,
6750           length = array.length,
6751           lastIndex = length - 1;
6752
6753       size = size === undefined ? length : size;
6754       while (++index < size) {
6755         var rand = baseRandom(index, lastIndex),
6756             value = array[rand];
6757
6758         array[rand] = array[index];
6759         array[index] = value;
6760       }
6761       array.length = size;
6762       return array;
6763     }
6764
6765     /**
6766      * Converts `string` to a property path array.
6767      *
6768      * @private
6769      * @param {string} string The string to convert.
6770      * @returns {Array} Returns the property path array.
6771      */
6772     var stringToPath = memoizeCapped(function(string) {
6773       var result = [];
6774       if (reLeadingDot.test(string)) {
6775         result.push('');
6776       }
6777       string.replace(rePropName, function(match, number, quote, string) {
6778         result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6779       });
6780       return result;
6781     });
6782
6783     /**
6784      * Converts `value` to a string key if it's not a string or symbol.
6785      *
6786      * @private
6787      * @param {*} value The value to inspect.
6788      * @returns {string|symbol} Returns the key.
6789      */
6790     function toKey(value) {
6791       if (typeof value == 'string' || isSymbol(value)) {
6792         return value;
6793       }
6794       var result = (value + '');
6795       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6796     }
6797
6798     /**
6799      * Converts `func` to its source code.
6800      *
6801      * @private
6802      * @param {Function} func The function to convert.
6803      * @returns {string} Returns the source code.
6804      */
6805     function toSource(func) {
6806       if (func != null) {
6807         try {
6808           return funcToString.call(func);
6809         } catch (e) {}
6810         try {
6811           return (func + '');
6812         } catch (e) {}
6813       }
6814       return '';
6815     }
6816
6817     /**
6818      * Updates wrapper `details` based on `bitmask` flags.
6819      *
6820      * @private
6821      * @returns {Array} details The details to modify.
6822      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6823      * @returns {Array} Returns `details`.
6824      */
6825     function updateWrapDetails(details, bitmask) {
6826       arrayEach(wrapFlags, function(pair) {
6827         var value = '_.' + pair[0];
6828         if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6829           details.push(value);
6830         }
6831       });
6832       return details.sort();
6833     }
6834
6835     /**
6836      * Creates a clone of `wrapper`.
6837      *
6838      * @private
6839      * @param {Object} wrapper The wrapper to clone.
6840      * @returns {Object} Returns the cloned wrapper.
6841      */
6842     function wrapperClone(wrapper) {
6843       if (wrapper instanceof LazyWrapper) {
6844         return wrapper.clone();
6845       }
6846       var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6847       result.__actions__ = copyArray(wrapper.__actions__);
6848       result.__index__  = wrapper.__index__;
6849       result.__values__ = wrapper.__values__;
6850       return result;
6851     }
6852
6853     /*------------------------------------------------------------------------*/
6854
6855     /**
6856      * Creates an array of elements split into groups the length of `size`.
6857      * If `array` can't be split evenly, the final chunk will be the remaining
6858      * elements.
6859      *
6860      * @static
6861      * @memberOf _
6862      * @since 3.0.0
6863      * @category Array
6864      * @param {Array} array The array to process.
6865      * @param {number} [size=1] The length of each chunk
6866      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6867      * @returns {Array} Returns the new array of chunks.
6868      * @example
6869      *
6870      * _.chunk(['a', 'b', 'c', 'd'], 2);
6871      * // => [['a', 'b'], ['c', 'd']]
6872      *
6873      * _.chunk(['a', 'b', 'c', 'd'], 3);
6874      * // => [['a', 'b', 'c'], ['d']]
6875      */
6876     function chunk(array, size, guard) {
6877       if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6878         size = 1;
6879       } else {
6880         size = nativeMax(toInteger(size), 0);
6881       }
6882       var length = array == null ? 0 : array.length;
6883       if (!length || size < 1) {
6884         return [];
6885       }
6886       var index = 0,
6887           resIndex = 0,
6888           result = Array(nativeCeil(length / size));
6889
6890       while (index < length) {
6891         result[resIndex++] = baseSlice(array, index, (index += size));
6892       }
6893       return result;
6894     }
6895
6896     /**
6897      * Creates an array with all falsey values removed. The values `false`, `null`,
6898      * `0`, `""`, `undefined`, and `NaN` are falsey.
6899      *
6900      * @static
6901      * @memberOf _
6902      * @since 0.1.0
6903      * @category Array
6904      * @param {Array} array The array to compact.
6905      * @returns {Array} Returns the new array of filtered values.
6906      * @example
6907      *
6908      * _.compact([0, 1, false, 2, '', 3]);
6909      * // => [1, 2, 3]
6910      */
6911     function compact(array) {
6912       var index = -1,
6913           length = array == null ? 0 : array.length,
6914           resIndex = 0,
6915           result = [];
6916
6917       while (++index < length) {
6918         var value = array[index];
6919         if (value) {
6920           result[resIndex++] = value;
6921         }
6922       }
6923       return result;
6924     }
6925
6926     /**
6927      * Creates a new array concatenating `array` with any additional arrays
6928      * and/or values.
6929      *
6930      * @static
6931      * @memberOf _
6932      * @since 4.0.0
6933      * @category Array
6934      * @param {Array} array The array to concatenate.
6935      * @param {...*} [values] The values to concatenate.
6936      * @returns {Array} Returns the new concatenated array.
6937      * @example
6938      *
6939      * var array = [1];
6940      * var other = _.concat(array, 2, [3], [[4]]);
6941      *
6942      * console.log(other);
6943      * // => [1, 2, 3, [4]]
6944      *
6945      * console.log(array);
6946      * // => [1]
6947      */
6948     function concat() {
6949       var length = arguments.length;
6950       if (!length) {
6951         return [];
6952       }
6953       var args = Array(length - 1),
6954           array = arguments[0],
6955           index = length;
6956
6957       while (index--) {
6958         args[index - 1] = arguments[index];
6959       }
6960       return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6961     }
6962
6963     /**
6964      * Creates an array of `array` values not included in the other given arrays
6965      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6966      * for equality comparisons. The order and references of result values are
6967      * determined by the first array.
6968      *
6969      * **Note:** Unlike `_.pullAll`, this method returns a new array.
6970      *
6971      * @static
6972      * @memberOf _
6973      * @since 0.1.0
6974      * @category Array
6975      * @param {Array} array The array to inspect.
6976      * @param {...Array} [values] The values to exclude.
6977      * @returns {Array} Returns the new array of filtered values.
6978      * @see _.without, _.xor
6979      * @example
6980      *
6981      * _.difference([2, 1], [2, 3]);
6982      * // => [1]
6983      */
6984     var difference = baseRest(function(array, values) {
6985       return isArrayLikeObject(array)
6986         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6987         : [];
6988     });
6989
6990     /**
6991      * This method is like `_.difference` except that it accepts `iteratee` which
6992      * is invoked for each element of `array` and `values` to generate the criterion
6993      * by which they're compared. The order and references of result values are
6994      * determined by the first array. The iteratee is invoked with one argument:
6995      * (value).
6996      *
6997      * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
6998      *
6999      * @static
7000      * @memberOf _
7001      * @since 4.0.0
7002      * @category Array
7003      * @param {Array} array The array to inspect.
7004      * @param {...Array} [values] The values to exclude.
7005      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7006      * @returns {Array} Returns the new array of filtered values.
7007      * @example
7008      *
7009      * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7010      * // => [1.2]
7011      *
7012      * // The `_.property` iteratee shorthand.
7013      * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
7014      * // => [{ 'x': 2 }]
7015      */
7016     var differenceBy = baseRest(function(array, values) {
7017       var iteratee = last(values);
7018       if (isArrayLikeObject(iteratee)) {
7019         iteratee = undefined;
7020       }
7021       return isArrayLikeObject(array)
7022         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7023         : [];
7024     });
7025
7026     /**
7027      * This method is like `_.difference` except that it accepts `comparator`
7028      * which is invoked to compare elements of `array` to `values`. The order and
7029      * references of result values are determined by the first array. The comparator
7030      * is invoked with two arguments: (arrVal, othVal).
7031      *
7032      * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7033      *
7034      * @static
7035      * @memberOf _
7036      * @since 4.0.0
7037      * @category Array
7038      * @param {Array} array The array to inspect.
7039      * @param {...Array} [values] The values to exclude.
7040      * @param {Function} [comparator] The comparator invoked per element.
7041      * @returns {Array} Returns the new array of filtered values.
7042      * @example
7043      *
7044      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7045      *
7046      * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7047      * // => [{ 'x': 2, 'y': 1 }]
7048      */
7049     var differenceWith = baseRest(function(array, values) {
7050       var comparator = last(values);
7051       if (isArrayLikeObject(comparator)) {
7052         comparator = undefined;
7053       }
7054       return isArrayLikeObject(array)
7055         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7056         : [];
7057     });
7058
7059     /**
7060      * Creates a slice of `array` with `n` elements dropped from the beginning.
7061      *
7062      * @static
7063      * @memberOf _
7064      * @since 0.5.0
7065      * @category Array
7066      * @param {Array} array The array to query.
7067      * @param {number} [n=1] The number of elements to drop.
7068      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7069      * @returns {Array} Returns the slice of `array`.
7070      * @example
7071      *
7072      * _.drop([1, 2, 3]);
7073      * // => [2, 3]
7074      *
7075      * _.drop([1, 2, 3], 2);
7076      * // => [3]
7077      *
7078      * _.drop([1, 2, 3], 5);
7079      * // => []
7080      *
7081      * _.drop([1, 2, 3], 0);
7082      * // => [1, 2, 3]
7083      */
7084     function drop(array, n, guard) {
7085       var length = array == null ? 0 : array.length;
7086       if (!length) {
7087         return [];
7088       }
7089       n = (guard || n === undefined) ? 1 : toInteger(n);
7090       return baseSlice(array, n < 0 ? 0 : n, length);
7091     }
7092
7093     /**
7094      * Creates a slice of `array` with `n` elements dropped from the end.
7095      *
7096      * @static
7097      * @memberOf _
7098      * @since 3.0.0
7099      * @category Array
7100      * @param {Array} array The array to query.
7101      * @param {number} [n=1] The number of elements to drop.
7102      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7103      * @returns {Array} Returns the slice of `array`.
7104      * @example
7105      *
7106      * _.dropRight([1, 2, 3]);
7107      * // => [1, 2]
7108      *
7109      * _.dropRight([1, 2, 3], 2);
7110      * // => [1]
7111      *
7112      * _.dropRight([1, 2, 3], 5);
7113      * // => []
7114      *
7115      * _.dropRight([1, 2, 3], 0);
7116      * // => [1, 2, 3]
7117      */
7118     function dropRight(array, n, guard) {
7119       var length = array == null ? 0 : array.length;
7120       if (!length) {
7121         return [];
7122       }
7123       n = (guard || n === undefined) ? 1 : toInteger(n);
7124       n = length - n;
7125       return baseSlice(array, 0, n < 0 ? 0 : n);
7126     }
7127
7128     /**
7129      * Creates a slice of `array` excluding elements dropped from the end.
7130      * Elements are dropped until `predicate` returns falsey. The predicate is
7131      * invoked with three arguments: (value, index, array).
7132      *
7133      * @static
7134      * @memberOf _
7135      * @since 3.0.0
7136      * @category Array
7137      * @param {Array} array The array to query.
7138      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7139      * @returns {Array} Returns the slice of `array`.
7140      * @example
7141      *
7142      * var users = [
7143      *   { 'user': 'barney',  'active': true },
7144      *   { 'user': 'fred',    'active': false },
7145      *   { 'user': 'pebbles', 'active': false }
7146      * ];
7147      *
7148      * _.dropRightWhile(users, function(o) { return !o.active; });
7149      * // => objects for ['barney']
7150      *
7151      * // The `_.matches` iteratee shorthand.
7152      * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7153      * // => objects for ['barney', 'fred']
7154      *
7155      * // The `_.matchesProperty` iteratee shorthand.
7156      * _.dropRightWhile(users, ['active', false]);
7157      * // => objects for ['barney']
7158      *
7159      * // The `_.property` iteratee shorthand.
7160      * _.dropRightWhile(users, 'active');
7161      * // => objects for ['barney', 'fred', 'pebbles']
7162      */
7163     function dropRightWhile(array, predicate) {
7164       return (array && array.length)
7165         ? baseWhile(array, getIteratee(predicate, 3), true, true)
7166         : [];
7167     }
7168
7169     /**
7170      * Creates a slice of `array` excluding elements dropped from the beginning.
7171      * Elements are dropped until `predicate` returns falsey. The predicate is
7172      * invoked with three arguments: (value, index, array).
7173      *
7174      * @static
7175      * @memberOf _
7176      * @since 3.0.0
7177      * @category Array
7178      * @param {Array} array The array to query.
7179      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7180      * @returns {Array} Returns the slice of `array`.
7181      * @example
7182      *
7183      * var users = [
7184      *   { 'user': 'barney',  'active': false },
7185      *   { 'user': 'fred',    'active': false },
7186      *   { 'user': 'pebbles', 'active': true }
7187      * ];
7188      *
7189      * _.dropWhile(users, function(o) { return !o.active; });
7190      * // => objects for ['pebbles']
7191      *
7192      * // The `_.matches` iteratee shorthand.
7193      * _.dropWhile(users, { 'user': 'barney', 'active': false });
7194      * // => objects for ['fred', 'pebbles']
7195      *
7196      * // The `_.matchesProperty` iteratee shorthand.
7197      * _.dropWhile(users, ['active', false]);
7198      * // => objects for ['pebbles']
7199      *
7200      * // The `_.property` iteratee shorthand.
7201      * _.dropWhile(users, 'active');
7202      * // => objects for ['barney', 'fred', 'pebbles']
7203      */
7204     function dropWhile(array, predicate) {
7205       return (array && array.length)
7206         ? baseWhile(array, getIteratee(predicate, 3), true)
7207         : [];
7208     }
7209
7210     /**
7211      * Fills elements of `array` with `value` from `start` up to, but not
7212      * including, `end`.
7213      *
7214      * **Note:** This method mutates `array`.
7215      *
7216      * @static
7217      * @memberOf _
7218      * @since 3.2.0
7219      * @category Array
7220      * @param {Array} array The array to fill.
7221      * @param {*} value The value to fill `array` with.
7222      * @param {number} [start=0] The start position.
7223      * @param {number} [end=array.length] The end position.
7224      * @returns {Array} Returns `array`.
7225      * @example
7226      *
7227      * var array = [1, 2, 3];
7228      *
7229      * _.fill(array, 'a');
7230      * console.log(array);
7231      * // => ['a', 'a', 'a']
7232      *
7233      * _.fill(Array(3), 2);
7234      * // => [2, 2, 2]
7235      *
7236      * _.fill([4, 6, 8, 10], '*', 1, 3);
7237      * // => [4, '*', '*', 10]
7238      */
7239     function fill(array, value, start, end) {
7240       var length = array == null ? 0 : array.length;
7241       if (!length) {
7242         return [];
7243       }
7244       if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7245         start = 0;
7246         end = length;
7247       }
7248       return baseFill(array, value, start, end);
7249     }
7250
7251     /**
7252      * This method is like `_.find` except that it returns the index of the first
7253      * element `predicate` returns truthy for instead of the element itself.
7254      *
7255      * @static
7256      * @memberOf _
7257      * @since 1.1.0
7258      * @category Array
7259      * @param {Array} array The array to inspect.
7260      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7261      * @param {number} [fromIndex=0] The index to search from.
7262      * @returns {number} Returns the index of the found element, else `-1`.
7263      * @example
7264      *
7265      * var users = [
7266      *   { 'user': 'barney',  'active': false },
7267      *   { 'user': 'fred',    'active': false },
7268      *   { 'user': 'pebbles', 'active': true }
7269      * ];
7270      *
7271      * _.findIndex(users, function(o) { return o.user == 'barney'; });
7272      * // => 0
7273      *
7274      * // The `_.matches` iteratee shorthand.
7275      * _.findIndex(users, { 'user': 'fred', 'active': false });
7276      * // => 1
7277      *
7278      * // The `_.matchesProperty` iteratee shorthand.
7279      * _.findIndex(users, ['active', false]);
7280      * // => 0
7281      *
7282      * // The `_.property` iteratee shorthand.
7283      * _.findIndex(users, 'active');
7284      * // => 2
7285      */
7286     function findIndex(array, predicate, fromIndex) {
7287       var length = array == null ? 0 : array.length;
7288       if (!length) {
7289         return -1;
7290       }
7291       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7292       if (index < 0) {
7293         index = nativeMax(length + index, 0);
7294       }
7295       return baseFindIndex(array, getIteratee(predicate, 3), index);
7296     }
7297
7298     /**
7299      * This method is like `_.findIndex` except that it iterates over elements
7300      * of `collection` from right to left.
7301      *
7302      * @static
7303      * @memberOf _
7304      * @since 2.0.0
7305      * @category Array
7306      * @param {Array} array The array to inspect.
7307      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7308      * @param {number} [fromIndex=array.length-1] The index to search from.
7309      * @returns {number} Returns the index of the found element, else `-1`.
7310      * @example
7311      *
7312      * var users = [
7313      *   { 'user': 'barney',  'active': true },
7314      *   { 'user': 'fred',    'active': false },
7315      *   { 'user': 'pebbles', 'active': false }
7316      * ];
7317      *
7318      * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7319      * // => 2
7320      *
7321      * // The `_.matches` iteratee shorthand.
7322      * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7323      * // => 0
7324      *
7325      * // The `_.matchesProperty` iteratee shorthand.
7326      * _.findLastIndex(users, ['active', false]);
7327      * // => 2
7328      *
7329      * // The `_.property` iteratee shorthand.
7330      * _.findLastIndex(users, 'active');
7331      * // => 0
7332      */
7333     function findLastIndex(array, predicate, fromIndex) {
7334       var length = array == null ? 0 : array.length;
7335       if (!length) {
7336         return -1;
7337       }
7338       var index = length - 1;
7339       if (fromIndex !== undefined) {
7340         index = toInteger(fromIndex);
7341         index = fromIndex < 0
7342           ? nativeMax(length + index, 0)
7343           : nativeMin(index, length - 1);
7344       }
7345       return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7346     }
7347
7348     /**
7349      * Flattens `array` a single level deep.
7350      *
7351      * @static
7352      * @memberOf _
7353      * @since 0.1.0
7354      * @category Array
7355      * @param {Array} array The array to flatten.
7356      * @returns {Array} Returns the new flattened array.
7357      * @example
7358      *
7359      * _.flatten([1, [2, [3, [4]], 5]]);
7360      * // => [1, 2, [3, [4]], 5]
7361      */
7362     function flatten(array) {
7363       var length = array == null ? 0 : array.length;
7364       return length ? baseFlatten(array, 1) : [];
7365     }
7366
7367     /**
7368      * Recursively flattens `array`.
7369      *
7370      * @static
7371      * @memberOf _
7372      * @since 3.0.0
7373      * @category Array
7374      * @param {Array} array The array to flatten.
7375      * @returns {Array} Returns the new flattened array.
7376      * @example
7377      *
7378      * _.flattenDeep([1, [2, [3, [4]], 5]]);
7379      * // => [1, 2, 3, 4, 5]
7380      */
7381     function flattenDeep(array) {
7382       var length = array == null ? 0 : array.length;
7383       return length ? baseFlatten(array, INFINITY) : [];
7384     }
7385
7386     /**
7387      * Recursively flatten `array` up to `depth` times.
7388      *
7389      * @static
7390      * @memberOf _
7391      * @since 4.4.0
7392      * @category Array
7393      * @param {Array} array The array to flatten.
7394      * @param {number} [depth=1] The maximum recursion depth.
7395      * @returns {Array} Returns the new flattened array.
7396      * @example
7397      *
7398      * var array = [1, [2, [3, [4]], 5]];
7399      *
7400      * _.flattenDepth(array, 1);
7401      * // => [1, 2, [3, [4]], 5]
7402      *
7403      * _.flattenDepth(array, 2);
7404      * // => [1, 2, 3, [4], 5]
7405      */
7406     function flattenDepth(array, depth) {
7407       var length = array == null ? 0 : array.length;
7408       if (!length) {
7409         return [];
7410       }
7411       depth = depth === undefined ? 1 : toInteger(depth);
7412       return baseFlatten(array, depth);
7413     }
7414
7415     /**
7416      * The inverse of `_.toPairs`; this method returns an object composed
7417      * from key-value `pairs`.
7418      *
7419      * @static
7420      * @memberOf _
7421      * @since 4.0.0
7422      * @category Array
7423      * @param {Array} pairs The key-value pairs.
7424      * @returns {Object} Returns the new object.
7425      * @example
7426      *
7427      * _.fromPairs([['a', 1], ['b', 2]]);
7428      * // => { 'a': 1, 'b': 2 }
7429      */
7430     function fromPairs(pairs) {
7431       var index = -1,
7432           length = pairs == null ? 0 : pairs.length,
7433           result = {};
7434
7435       while (++index < length) {
7436         var pair = pairs[index];
7437         result[pair[0]] = pair[1];
7438       }
7439       return result;
7440     }
7441
7442     /**
7443      * Gets the first element of `array`.
7444      *
7445      * @static
7446      * @memberOf _
7447      * @since 0.1.0
7448      * @alias first
7449      * @category Array
7450      * @param {Array} array The array to query.
7451      * @returns {*} Returns the first element of `array`.
7452      * @example
7453      *
7454      * _.head([1, 2, 3]);
7455      * // => 1
7456      *
7457      * _.head([]);
7458      * // => undefined
7459      */
7460     function head(array) {
7461       return (array && array.length) ? array[0] : undefined;
7462     }
7463
7464     /**
7465      * Gets the index at which the first occurrence of `value` is found in `array`
7466      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7467      * for equality comparisons. If `fromIndex` is negative, it's used as the
7468      * offset from the end of `array`.
7469      *
7470      * @static
7471      * @memberOf _
7472      * @since 0.1.0
7473      * @category Array
7474      * @param {Array} array The array to inspect.
7475      * @param {*} value The value to search for.
7476      * @param {number} [fromIndex=0] The index to search from.
7477      * @returns {number} Returns the index of the matched value, else `-1`.
7478      * @example
7479      *
7480      * _.indexOf([1, 2, 1, 2], 2);
7481      * // => 1
7482      *
7483      * // Search from the `fromIndex`.
7484      * _.indexOf([1, 2, 1, 2], 2, 2);
7485      * // => 3
7486      */
7487     function indexOf(array, value, fromIndex) {
7488       var length = array == null ? 0 : array.length;
7489       if (!length) {
7490         return -1;
7491       }
7492       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7493       if (index < 0) {
7494         index = nativeMax(length + index, 0);
7495       }
7496       return baseIndexOf(array, value, index);
7497     }
7498
7499     /**
7500      * Gets all but the last element of `array`.
7501      *
7502      * @static
7503      * @memberOf _
7504      * @since 0.1.0
7505      * @category Array
7506      * @param {Array} array The array to query.
7507      * @returns {Array} Returns the slice of `array`.
7508      * @example
7509      *
7510      * _.initial([1, 2, 3]);
7511      * // => [1, 2]
7512      */
7513     function initial(array) {
7514       var length = array == null ? 0 : array.length;
7515       return length ? baseSlice(array, 0, -1) : [];
7516     }
7517
7518     /**
7519      * Creates an array of unique values that are included in all given arrays
7520      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7521      * for equality comparisons. The order and references of result values are
7522      * determined by the first array.
7523      *
7524      * @static
7525      * @memberOf _
7526      * @since 0.1.0
7527      * @category Array
7528      * @param {...Array} [arrays] The arrays to inspect.
7529      * @returns {Array} Returns the new array of intersecting values.
7530      * @example
7531      *
7532      * _.intersection([2, 1], [2, 3]);
7533      * // => [2]
7534      */
7535     var intersection = baseRest(function(arrays) {
7536       var mapped = arrayMap(arrays, castArrayLikeObject);
7537       return (mapped.length && mapped[0] === arrays[0])
7538         ? baseIntersection(mapped)
7539         : [];
7540     });
7541
7542     /**
7543      * This method is like `_.intersection` except that it accepts `iteratee`
7544      * which is invoked for each element of each `arrays` to generate the criterion
7545      * by which they're compared. The order and references of result values are
7546      * determined by the first array. The iteratee is invoked with one argument:
7547      * (value).
7548      *
7549      * @static
7550      * @memberOf _
7551      * @since 4.0.0
7552      * @category Array
7553      * @param {...Array} [arrays] The arrays to inspect.
7554      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7555      * @returns {Array} Returns the new array of intersecting values.
7556      * @example
7557      *
7558      * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7559      * // => [2.1]
7560      *
7561      * // The `_.property` iteratee shorthand.
7562      * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7563      * // => [{ 'x': 1 }]
7564      */
7565     var intersectionBy = baseRest(function(arrays) {
7566       var iteratee = last(arrays),
7567           mapped = arrayMap(arrays, castArrayLikeObject);
7568
7569       if (iteratee === last(mapped)) {
7570         iteratee = undefined;
7571       } else {
7572         mapped.pop();
7573       }
7574       return (mapped.length && mapped[0] === arrays[0])
7575         ? baseIntersection(mapped, getIteratee(iteratee, 2))
7576         : [];
7577     });
7578
7579     /**
7580      * This method is like `_.intersection` except that it accepts `comparator`
7581      * which is invoked to compare elements of `arrays`. The order and references
7582      * of result values are determined by the first array. The comparator is
7583      * invoked with two arguments: (arrVal, othVal).
7584      *
7585      * @static
7586      * @memberOf _
7587      * @since 4.0.0
7588      * @category Array
7589      * @param {...Array} [arrays] The arrays to inspect.
7590      * @param {Function} [comparator] The comparator invoked per element.
7591      * @returns {Array} Returns the new array of intersecting values.
7592      * @example
7593      *
7594      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7595      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7596      *
7597      * _.intersectionWith(objects, others, _.isEqual);
7598      * // => [{ 'x': 1, 'y': 2 }]
7599      */
7600     var intersectionWith = baseRest(function(arrays) {
7601       var comparator = last(arrays),
7602           mapped = arrayMap(arrays, castArrayLikeObject);
7603
7604       comparator = typeof comparator == 'function' ? comparator : undefined;
7605       if (comparator) {
7606         mapped.pop();
7607       }
7608       return (mapped.length && mapped[0] === arrays[0])
7609         ? baseIntersection(mapped, undefined, comparator)
7610         : [];
7611     });
7612
7613     /**
7614      * Converts all elements in `array` into a string separated by `separator`.
7615      *
7616      * @static
7617      * @memberOf _
7618      * @since 4.0.0
7619      * @category Array
7620      * @param {Array} array The array to convert.
7621      * @param {string} [separator=','] The element separator.
7622      * @returns {string} Returns the joined string.
7623      * @example
7624      *
7625      * _.join(['a', 'b', 'c'], '~');
7626      * // => 'a~b~c'
7627      */
7628     function join(array, separator) {
7629       return array == null ? '' : nativeJoin.call(array, separator);
7630     }
7631
7632     /**
7633      * Gets the last element of `array`.
7634      *
7635      * @static
7636      * @memberOf _
7637      * @since 0.1.0
7638      * @category Array
7639      * @param {Array} array The array to query.
7640      * @returns {*} Returns the last element of `array`.
7641      * @example
7642      *
7643      * _.last([1, 2, 3]);
7644      * // => 3
7645      */
7646     function last(array) {
7647       var length = array == null ? 0 : array.length;
7648       return length ? array[length - 1] : undefined;
7649     }
7650
7651     /**
7652      * This method is like `_.indexOf` except that it iterates over elements of
7653      * `array` from right to left.
7654      *
7655      * @static
7656      * @memberOf _
7657      * @since 0.1.0
7658      * @category Array
7659      * @param {Array} array The array to inspect.
7660      * @param {*} value The value to search for.
7661      * @param {number} [fromIndex=array.length-1] The index to search from.
7662      * @returns {number} Returns the index of the matched value, else `-1`.
7663      * @example
7664      *
7665      * _.lastIndexOf([1, 2, 1, 2], 2);
7666      * // => 3
7667      *
7668      * // Search from the `fromIndex`.
7669      * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7670      * // => 1
7671      */
7672     function lastIndexOf(array, value, fromIndex) {
7673       var length = array == null ? 0 : array.length;
7674       if (!length) {
7675         return -1;
7676       }
7677       var index = length;
7678       if (fromIndex !== undefined) {
7679         index = toInteger(fromIndex);
7680         index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7681       }
7682       return value === value
7683         ? strictLastIndexOf(array, value, index)
7684         : baseFindIndex(array, baseIsNaN, index, true);
7685     }
7686
7687     /**
7688      * Gets the element at index `n` of `array`. If `n` is negative, the nth
7689      * element from the end is returned.
7690      *
7691      * @static
7692      * @memberOf _
7693      * @since 4.11.0
7694      * @category Array
7695      * @param {Array} array The array to query.
7696      * @param {number} [n=0] The index of the element to return.
7697      * @returns {*} Returns the nth element of `array`.
7698      * @example
7699      *
7700      * var array = ['a', 'b', 'c', 'd'];
7701      *
7702      * _.nth(array, 1);
7703      * // => 'b'
7704      *
7705      * _.nth(array, -2);
7706      * // => 'c';
7707      */
7708     function nth(array, n) {
7709       return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7710     }
7711
7712     /**
7713      * Removes all given values from `array` using
7714      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7715      * for equality comparisons.
7716      *
7717      * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7718      * to remove elements from an array by predicate.
7719      *
7720      * @static
7721      * @memberOf _
7722      * @since 2.0.0
7723      * @category Array
7724      * @param {Array} array The array to modify.
7725      * @param {...*} [values] The values to remove.
7726      * @returns {Array} Returns `array`.
7727      * @example
7728      *
7729      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7730      *
7731      * _.pull(array, 'a', 'c');
7732      * console.log(array);
7733      * // => ['b', 'b']
7734      */
7735     var pull = baseRest(pullAll);
7736
7737     /**
7738      * This method is like `_.pull` except that it accepts an array of values to remove.
7739      *
7740      * **Note:** Unlike `_.difference`, this method mutates `array`.
7741      *
7742      * @static
7743      * @memberOf _
7744      * @since 4.0.0
7745      * @category Array
7746      * @param {Array} array The array to modify.
7747      * @param {Array} values The values to remove.
7748      * @returns {Array} Returns `array`.
7749      * @example
7750      *
7751      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7752      *
7753      * _.pullAll(array, ['a', 'c']);
7754      * console.log(array);
7755      * // => ['b', 'b']
7756      */
7757     function pullAll(array, values) {
7758       return (array && array.length && values && values.length)
7759         ? basePullAll(array, values)
7760         : array;
7761     }
7762
7763     /**
7764      * This method is like `_.pullAll` except that it accepts `iteratee` which is
7765      * invoked for each element of `array` and `values` to generate the criterion
7766      * by which they're compared. The iteratee is invoked with one argument: (value).
7767      *
7768      * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7769      *
7770      * @static
7771      * @memberOf _
7772      * @since 4.0.0
7773      * @category Array
7774      * @param {Array} array The array to modify.
7775      * @param {Array} values The values to remove.
7776      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7777      * @returns {Array} Returns `array`.
7778      * @example
7779      *
7780      * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7781      *
7782      * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7783      * console.log(array);
7784      * // => [{ 'x': 2 }]
7785      */
7786     function pullAllBy(array, values, iteratee) {
7787       return (array && array.length && values && values.length)
7788         ? basePullAll(array, values, getIteratee(iteratee, 2))
7789         : array;
7790     }
7791
7792     /**
7793      * This method is like `_.pullAll` except that it accepts `comparator` which
7794      * is invoked to compare elements of `array` to `values`. The comparator is
7795      * invoked with two arguments: (arrVal, othVal).
7796      *
7797      * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7798      *
7799      * @static
7800      * @memberOf _
7801      * @since 4.6.0
7802      * @category Array
7803      * @param {Array} array The array to modify.
7804      * @param {Array} values The values to remove.
7805      * @param {Function} [comparator] The comparator invoked per element.
7806      * @returns {Array} Returns `array`.
7807      * @example
7808      *
7809      * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7810      *
7811      * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7812      * console.log(array);
7813      * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7814      */
7815     function pullAllWith(array, values, comparator) {
7816       return (array && array.length && values && values.length)
7817         ? basePullAll(array, values, undefined, comparator)
7818         : array;
7819     }
7820
7821     /**
7822      * Removes elements from `array` corresponding to `indexes` and returns an
7823      * array of removed elements.
7824      *
7825      * **Note:** Unlike `_.at`, this method mutates `array`.
7826      *
7827      * @static
7828      * @memberOf _
7829      * @since 3.0.0
7830      * @category Array
7831      * @param {Array} array The array to modify.
7832      * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7833      * @returns {Array} Returns the new array of removed elements.
7834      * @example
7835      *
7836      * var array = ['a', 'b', 'c', 'd'];
7837      * var pulled = _.pullAt(array, [1, 3]);
7838      *
7839      * console.log(array);
7840      * // => ['a', 'c']
7841      *
7842      * console.log(pulled);
7843      * // => ['b', 'd']
7844      */
7845     var pullAt = flatRest(function(array, indexes) {
7846       var length = array == null ? 0 : array.length,
7847           result = baseAt(array, indexes);
7848
7849       basePullAt(array, arrayMap(indexes, function(index) {
7850         return isIndex(index, length) ? +index : index;
7851       }).sort(compareAscending));
7852
7853       return result;
7854     });
7855
7856     /**
7857      * Removes all elements from `array` that `predicate` returns truthy for
7858      * and returns an array of the removed elements. The predicate is invoked
7859      * with three arguments: (value, index, array).
7860      *
7861      * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7862      * to pull elements from an array by value.
7863      *
7864      * @static
7865      * @memberOf _
7866      * @since 2.0.0
7867      * @category Array
7868      * @param {Array} array The array to modify.
7869      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7870      * @returns {Array} Returns the new array of removed elements.
7871      * @example
7872      *
7873      * var array = [1, 2, 3, 4];
7874      * var evens = _.remove(array, function(n) {
7875      *   return n % 2 == 0;
7876      * });
7877      *
7878      * console.log(array);
7879      * // => [1, 3]
7880      *
7881      * console.log(evens);
7882      * // => [2, 4]
7883      */
7884     function remove(array, predicate) {
7885       var result = [];
7886       if (!(array && array.length)) {
7887         return result;
7888       }
7889       var index = -1,
7890           indexes = [],
7891           length = array.length;
7892
7893       predicate = getIteratee(predicate, 3);
7894       while (++index < length) {
7895         var value = array[index];
7896         if (predicate(value, index, array)) {
7897           result.push(value);
7898           indexes.push(index);
7899         }
7900       }
7901       basePullAt(array, indexes);
7902       return result;
7903     }
7904
7905     /**
7906      * Reverses `array` so that the first element becomes the last, the second
7907      * element becomes the second to last, and so on.
7908      *
7909      * **Note:** This method mutates `array` and is based on
7910      * [`Array#reverse`](https://mdn.io/Array/reverse).
7911      *
7912      * @static
7913      * @memberOf _
7914      * @since 4.0.0
7915      * @category Array
7916      * @param {Array} array The array to modify.
7917      * @returns {Array} Returns `array`.
7918      * @example
7919      *
7920      * var array = [1, 2, 3];
7921      *
7922      * _.reverse(array);
7923      * // => [3, 2, 1]
7924      *
7925      * console.log(array);
7926      * // => [3, 2, 1]
7927      */
7928     function reverse(array) {
7929       return array == null ? array : nativeReverse.call(array);
7930     }
7931
7932     /**
7933      * Creates a slice of `array` from `start` up to, but not including, `end`.
7934      *
7935      * **Note:** This method is used instead of
7936      * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7937      * returned.
7938      *
7939      * @static
7940      * @memberOf _
7941      * @since 3.0.0
7942      * @category Array
7943      * @param {Array} array The array to slice.
7944      * @param {number} [start=0] The start position.
7945      * @param {number} [end=array.length] The end position.
7946      * @returns {Array} Returns the slice of `array`.
7947      */
7948     function slice(array, start, end) {
7949       var length = array == null ? 0 : array.length;
7950       if (!length) {
7951         return [];
7952       }
7953       if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7954         start = 0;
7955         end = length;
7956       }
7957       else {
7958         start = start == null ? 0 : toInteger(start);
7959         end = end === undefined ? length : toInteger(end);
7960       }
7961       return baseSlice(array, start, end);
7962     }
7963
7964     /**
7965      * Uses a binary search to determine the lowest index at which `value`
7966      * should be inserted into `array` in order to maintain its sort order.
7967      *
7968      * @static
7969      * @memberOf _
7970      * @since 0.1.0
7971      * @category Array
7972      * @param {Array} array The sorted array to inspect.
7973      * @param {*} value The value to evaluate.
7974      * @returns {number} Returns the index at which `value` should be inserted
7975      *  into `array`.
7976      * @example
7977      *
7978      * _.sortedIndex([30, 50], 40);
7979      * // => 1
7980      */
7981     function sortedIndex(array, value) {
7982       return baseSortedIndex(array, value);
7983     }
7984
7985     /**
7986      * This method is like `_.sortedIndex` except that it accepts `iteratee`
7987      * which is invoked for `value` and each element of `array` to compute their
7988      * sort ranking. The iteratee is invoked with one argument: (value).
7989      *
7990      * @static
7991      * @memberOf _
7992      * @since 4.0.0
7993      * @category Array
7994      * @param {Array} array The sorted array to inspect.
7995      * @param {*} value The value to evaluate.
7996      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7997      * @returns {number} Returns the index at which `value` should be inserted
7998      *  into `array`.
7999      * @example
8000      *
8001      * var objects = [{ 'x': 4 }, { 'x': 5 }];
8002      *
8003      * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8004      * // => 0
8005      *
8006      * // The `_.property` iteratee shorthand.
8007      * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
8008      * // => 0
8009      */
8010     function sortedIndexBy(array, value, iteratee) {
8011       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
8012     }
8013
8014     /**
8015      * This method is like `_.indexOf` except that it performs a binary
8016      * search on a sorted `array`.
8017      *
8018      * @static
8019      * @memberOf _
8020      * @since 4.0.0
8021      * @category Array
8022      * @param {Array} array The array to inspect.
8023      * @param {*} value The value to search for.
8024      * @returns {number} Returns the index of the matched value, else `-1`.
8025      * @example
8026      *
8027      * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8028      * // => 1
8029      */
8030     function sortedIndexOf(array, value) {
8031       var length = array == null ? 0 : array.length;
8032       if (length) {
8033         var index = baseSortedIndex(array, value);
8034         if (index < length && eq(array[index], value)) {
8035           return index;
8036         }
8037       }
8038       return -1;
8039     }
8040
8041     /**
8042      * This method is like `_.sortedIndex` except that it returns the highest
8043      * index at which `value` should be inserted into `array` in order to
8044      * maintain its sort order.
8045      *
8046      * @static
8047      * @memberOf _
8048      * @since 3.0.0
8049      * @category Array
8050      * @param {Array} array The sorted array to inspect.
8051      * @param {*} value The value to evaluate.
8052      * @returns {number} Returns the index at which `value` should be inserted
8053      *  into `array`.
8054      * @example
8055      *
8056      * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8057      * // => 4
8058      */
8059     function sortedLastIndex(array, value) {
8060       return baseSortedIndex(array, value, true);
8061     }
8062
8063     /**
8064      * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8065      * which is invoked for `value` and each element of `array` to compute their
8066      * sort ranking. The iteratee is invoked with one argument: (value).
8067      *
8068      * @static
8069      * @memberOf _
8070      * @since 4.0.0
8071      * @category Array
8072      * @param {Array} array The sorted array to inspect.
8073      * @param {*} value The value to evaluate.
8074      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8075      * @returns {number} Returns the index at which `value` should be inserted
8076      *  into `array`.
8077      * @example
8078      *
8079      * var objects = [{ 'x': 4 }, { 'x': 5 }];
8080      *
8081      * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8082      * // => 1
8083      *
8084      * // The `_.property` iteratee shorthand.
8085      * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8086      * // => 1
8087      */
8088     function sortedLastIndexBy(array, value, iteratee) {
8089       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8090     }
8091
8092     /**
8093      * This method is like `_.lastIndexOf` except that it performs a binary
8094      * search on a sorted `array`.
8095      *
8096      * @static
8097      * @memberOf _
8098      * @since 4.0.0
8099      * @category Array
8100      * @param {Array} array The array to inspect.
8101      * @param {*} value The value to search for.
8102      * @returns {number} Returns the index of the matched value, else `-1`.
8103      * @example
8104      *
8105      * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8106      * // => 3
8107      */
8108     function sortedLastIndexOf(array, value) {
8109       var length = array == null ? 0 : array.length;
8110       if (length) {
8111         var index = baseSortedIndex(array, value, true) - 1;
8112         if (eq(array[index], value)) {
8113           return index;
8114         }
8115       }
8116       return -1;
8117     }
8118
8119     /**
8120      * This method is like `_.uniq` except that it's designed and optimized
8121      * for sorted arrays.
8122      *
8123      * @static
8124      * @memberOf _
8125      * @since 4.0.0
8126      * @category Array
8127      * @param {Array} array The array to inspect.
8128      * @returns {Array} Returns the new duplicate free array.
8129      * @example
8130      *
8131      * _.sortedUniq([1, 1, 2]);
8132      * // => [1, 2]
8133      */
8134     function sortedUniq(array) {
8135       return (array && array.length)
8136         ? baseSortedUniq(array)
8137         : [];
8138     }
8139
8140     /**
8141      * This method is like `_.uniqBy` except that it's designed and optimized
8142      * for sorted arrays.
8143      *
8144      * @static
8145      * @memberOf _
8146      * @since 4.0.0
8147      * @category Array
8148      * @param {Array} array The array to inspect.
8149      * @param {Function} [iteratee] The iteratee invoked per element.
8150      * @returns {Array} Returns the new duplicate free array.
8151      * @example
8152      *
8153      * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8154      * // => [1.1, 2.3]
8155      */
8156     function sortedUniqBy(array, iteratee) {
8157       return (array && array.length)
8158         ? baseSortedUniq(array, getIteratee(iteratee, 2))
8159         : [];
8160     }
8161
8162     /**
8163      * Gets all but the first element of `array`.
8164      *
8165      * @static
8166      * @memberOf _
8167      * @since 4.0.0
8168      * @category Array
8169      * @param {Array} array The array to query.
8170      * @returns {Array} Returns the slice of `array`.
8171      * @example
8172      *
8173      * _.tail([1, 2, 3]);
8174      * // => [2, 3]
8175      */
8176     function tail(array) {
8177       var length = array == null ? 0 : array.length;
8178       return length ? baseSlice(array, 1, length) : [];
8179     }
8180
8181     /**
8182      * Creates a slice of `array` with `n` elements taken from the beginning.
8183      *
8184      * @static
8185      * @memberOf _
8186      * @since 0.1.0
8187      * @category Array
8188      * @param {Array} array The array to query.
8189      * @param {number} [n=1] The number of elements to take.
8190      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8191      * @returns {Array} Returns the slice of `array`.
8192      * @example
8193      *
8194      * _.take([1, 2, 3]);
8195      * // => [1]
8196      *
8197      * _.take([1, 2, 3], 2);
8198      * // => [1, 2]
8199      *
8200      * _.take([1, 2, 3], 5);
8201      * // => [1, 2, 3]
8202      *
8203      * _.take([1, 2, 3], 0);
8204      * // => []
8205      */
8206     function take(array, n, guard) {
8207       if (!(array && array.length)) {
8208         return [];
8209       }
8210       n = (guard || n === undefined) ? 1 : toInteger(n);
8211       return baseSlice(array, 0, n < 0 ? 0 : n);
8212     }
8213
8214     /**
8215      * Creates a slice of `array` with `n` elements taken from the end.
8216      *
8217      * @static
8218      * @memberOf _
8219      * @since 3.0.0
8220      * @category Array
8221      * @param {Array} array The array to query.
8222      * @param {number} [n=1] The number of elements to take.
8223      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8224      * @returns {Array} Returns the slice of `array`.
8225      * @example
8226      *
8227      * _.takeRight([1, 2, 3]);
8228      * // => [3]
8229      *
8230      * _.takeRight([1, 2, 3], 2);
8231      * // => [2, 3]
8232      *
8233      * _.takeRight([1, 2, 3], 5);
8234      * // => [1, 2, 3]
8235      *
8236      * _.takeRight([1, 2, 3], 0);
8237      * // => []
8238      */
8239     function takeRight(array, n, guard) {
8240       var length = array == null ? 0 : array.length;
8241       if (!length) {
8242         return [];
8243       }
8244       n = (guard || n === undefined) ? 1 : toInteger(n);
8245       n = length - n;
8246       return baseSlice(array, n < 0 ? 0 : n, length);
8247     }
8248
8249     /**
8250      * Creates a slice of `array` with elements taken from the end. Elements are
8251      * taken until `predicate` returns falsey. The predicate is invoked with
8252      * three arguments: (value, index, array).
8253      *
8254      * @static
8255      * @memberOf _
8256      * @since 3.0.0
8257      * @category Array
8258      * @param {Array} array The array to query.
8259      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8260      * @returns {Array} Returns the slice of `array`.
8261      * @example
8262      *
8263      * var users = [
8264      *   { 'user': 'barney',  'active': true },
8265      *   { 'user': 'fred',    'active': false },
8266      *   { 'user': 'pebbles', 'active': false }
8267      * ];
8268      *
8269      * _.takeRightWhile(users, function(o) { return !o.active; });
8270      * // => objects for ['fred', 'pebbles']
8271      *
8272      * // The `_.matches` iteratee shorthand.
8273      * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8274      * // => objects for ['pebbles']
8275      *
8276      * // The `_.matchesProperty` iteratee shorthand.
8277      * _.takeRightWhile(users, ['active', false]);
8278      * // => objects for ['fred', 'pebbles']
8279      *
8280      * // The `_.property` iteratee shorthand.
8281      * _.takeRightWhile(users, 'active');
8282      * // => []
8283      */
8284     function takeRightWhile(array, predicate) {
8285       return (array && array.length)
8286         ? baseWhile(array, getIteratee(predicate, 3), false, true)
8287         : [];
8288     }
8289
8290     /**
8291      * Creates a slice of `array` with elements taken from the beginning. Elements
8292      * are taken until `predicate` returns falsey. The predicate is invoked with
8293      * three arguments: (value, index, array).
8294      *
8295      * @static
8296      * @memberOf _
8297      * @since 3.0.0
8298      * @category Array
8299      * @param {Array} array The array to query.
8300      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8301      * @returns {Array} Returns the slice of `array`.
8302      * @example
8303      *
8304      * var users = [
8305      *   { 'user': 'barney',  'active': false },
8306      *   { 'user': 'fred',    'active': false },
8307      *   { 'user': 'pebbles', 'active': true }
8308      * ];
8309      *
8310      * _.takeWhile(users, function(o) { return !o.active; });
8311      * // => objects for ['barney', 'fred']
8312      *
8313      * // The `_.matches` iteratee shorthand.
8314      * _.takeWhile(users, { 'user': 'barney', 'active': false });
8315      * // => objects for ['barney']
8316      *
8317      * // The `_.matchesProperty` iteratee shorthand.
8318      * _.takeWhile(users, ['active', false]);
8319      * // => objects for ['barney', 'fred']
8320      *
8321      * // The `_.property` iteratee shorthand.
8322      * _.takeWhile(users, 'active');
8323      * // => []
8324      */
8325     function takeWhile(array, predicate) {
8326       return (array && array.length)
8327         ? baseWhile(array, getIteratee(predicate, 3))
8328         : [];
8329     }
8330
8331     /**
8332      * Creates an array of unique values, in order, from all given arrays using
8333      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8334      * for equality comparisons.
8335      *
8336      * @static
8337      * @memberOf _
8338      * @since 0.1.0
8339      * @category Array
8340      * @param {...Array} [arrays] The arrays to inspect.
8341      * @returns {Array} Returns the new array of combined values.
8342      * @example
8343      *
8344      * _.union([2], [1, 2]);
8345      * // => [2, 1]
8346      */
8347     var union = baseRest(function(arrays) {
8348       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8349     });
8350
8351     /**
8352      * This method is like `_.union` except that it accepts `iteratee` which is
8353      * invoked for each element of each `arrays` to generate the criterion by
8354      * which uniqueness is computed. Result values are chosen from the first
8355      * array in which the value occurs. The iteratee is invoked with one argument:
8356      * (value).
8357      *
8358      * @static
8359      * @memberOf _
8360      * @since 4.0.0
8361      * @category Array
8362      * @param {...Array} [arrays] The arrays to inspect.
8363      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8364      * @returns {Array} Returns the new array of combined values.
8365      * @example
8366      *
8367      * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8368      * // => [2.1, 1.2]
8369      *
8370      * // The `_.property` iteratee shorthand.
8371      * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8372      * // => [{ 'x': 1 }, { 'x': 2 }]
8373      */
8374     var unionBy = baseRest(function(arrays) {
8375       var iteratee = last(arrays);
8376       if (isArrayLikeObject(iteratee)) {
8377         iteratee = undefined;
8378       }
8379       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8380     });
8381
8382     /**
8383      * This method is like `_.union` except that it accepts `comparator` which
8384      * is invoked to compare elements of `arrays`. Result values are chosen from
8385      * the first array in which the value occurs. The comparator is invoked
8386      * with two arguments: (arrVal, othVal).
8387      *
8388      * @static
8389      * @memberOf _
8390      * @since 4.0.0
8391      * @category Array
8392      * @param {...Array} [arrays] The arrays to inspect.
8393      * @param {Function} [comparator] The comparator invoked per element.
8394      * @returns {Array} Returns the new array of combined values.
8395      * @example
8396      *
8397      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8398      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8399      *
8400      * _.unionWith(objects, others, _.isEqual);
8401      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8402      */
8403     var unionWith = baseRest(function(arrays) {
8404       var comparator = last(arrays);
8405       comparator = typeof comparator == 'function' ? comparator : undefined;
8406       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8407     });
8408
8409     /**
8410      * Creates a duplicate-free version of an array, using
8411      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8412      * for equality comparisons, in which only the first occurrence of each element
8413      * is kept. The order of result values is determined by the order they occur
8414      * in the array.
8415      *
8416      * @static
8417      * @memberOf _
8418      * @since 0.1.0
8419      * @category Array
8420      * @param {Array} array The array to inspect.
8421      * @returns {Array} Returns the new duplicate free array.
8422      * @example
8423      *
8424      * _.uniq([2, 1, 2]);
8425      * // => [2, 1]
8426      */
8427     function uniq(array) {
8428       return (array && array.length) ? baseUniq(array) : [];
8429     }
8430
8431     /**
8432      * This method is like `_.uniq` except that it accepts `iteratee` which is
8433      * invoked for each element in `array` to generate the criterion by which
8434      * uniqueness is computed. The order of result values is determined by the
8435      * order they occur in the array. The iteratee is invoked with one argument:
8436      * (value).
8437      *
8438      * @static
8439      * @memberOf _
8440      * @since 4.0.0
8441      * @category Array
8442      * @param {Array} array The array to inspect.
8443      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8444      * @returns {Array} Returns the new duplicate free array.
8445      * @example
8446      *
8447      * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8448      * // => [2.1, 1.2]
8449      *
8450      * // The `_.property` iteratee shorthand.
8451      * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8452      * // => [{ 'x': 1 }, { 'x': 2 }]
8453      */
8454     function uniqBy(array, iteratee) {
8455       return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8456     }
8457
8458     /**
8459      * This method is like `_.uniq` except that it accepts `comparator` which
8460      * is invoked to compare elements of `array`. The order of result values is
8461      * determined by the order they occur in the array.The comparator is invoked
8462      * with two arguments: (arrVal, othVal).
8463      *
8464      * @static
8465      * @memberOf _
8466      * @since 4.0.0
8467      * @category Array
8468      * @param {Array} array The array to inspect.
8469      * @param {Function} [comparator] The comparator invoked per element.
8470      * @returns {Array} Returns the new duplicate free array.
8471      * @example
8472      *
8473      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8474      *
8475      * _.uniqWith(objects, _.isEqual);
8476      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8477      */
8478     function uniqWith(array, comparator) {
8479       comparator = typeof comparator == 'function' ? comparator : undefined;
8480       return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8481     }
8482
8483     /**
8484      * This method is like `_.zip` except that it accepts an array of grouped
8485      * elements and creates an array regrouping the elements to their pre-zip
8486      * configuration.
8487      *
8488      * @static
8489      * @memberOf _
8490      * @since 1.2.0
8491      * @category Array
8492      * @param {Array} array The array of grouped elements to process.
8493      * @returns {Array} Returns the new array of regrouped elements.
8494      * @example
8495      *
8496      * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8497      * // => [['a', 1, true], ['b', 2, false]]
8498      *
8499      * _.unzip(zipped);
8500      * // => [['a', 'b'], [1, 2], [true, false]]
8501      */
8502     function unzip(array) {
8503       if (!(array && array.length)) {
8504         return [];
8505       }
8506       var length = 0;
8507       array = arrayFilter(array, function(group) {
8508         if (isArrayLikeObject(group)) {
8509           length = nativeMax(group.length, length);
8510           return true;
8511         }
8512       });
8513       return baseTimes(length, function(index) {
8514         return arrayMap(array, baseProperty(index));
8515       });
8516     }
8517
8518     /**
8519      * This method is like `_.unzip` except that it accepts `iteratee` to specify
8520      * how regrouped values should be combined. The iteratee is invoked with the
8521      * elements of each group: (...group).
8522      *
8523      * @static
8524      * @memberOf _
8525      * @since 3.8.0
8526      * @category Array
8527      * @param {Array} array The array of grouped elements to process.
8528      * @param {Function} [iteratee=_.identity] The function to combine
8529      *  regrouped values.
8530      * @returns {Array} Returns the new array of regrouped elements.
8531      * @example
8532      *
8533      * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8534      * // => [[1, 10, 100], [2, 20, 200]]
8535      *
8536      * _.unzipWith(zipped, _.add);
8537      * // => [3, 30, 300]
8538      */
8539     function unzipWith(array, iteratee) {
8540       if (!(array && array.length)) {
8541         return [];
8542       }
8543       var result = unzip(array);
8544       if (iteratee == null) {
8545         return result;
8546       }
8547       return arrayMap(result, function(group) {
8548         return apply(iteratee, undefined, group);
8549       });
8550     }
8551
8552     /**
8553      * Creates an array excluding all given values using
8554      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8555      * for equality comparisons.
8556      *
8557      * **Note:** Unlike `_.pull`, this method returns a new array.
8558      *
8559      * @static
8560      * @memberOf _
8561      * @since 0.1.0
8562      * @category Array
8563      * @param {Array} array The array to inspect.
8564      * @param {...*} [values] The values to exclude.
8565      * @returns {Array} Returns the new array of filtered values.
8566      * @see _.difference, _.xor
8567      * @example
8568      *
8569      * _.without([2, 1, 2, 3], 1, 2);
8570      * // => [3]
8571      */
8572     var without = baseRest(function(array, values) {
8573       return isArrayLikeObject(array)
8574         ? baseDifference(array, values)
8575         : [];
8576     });
8577
8578     /**
8579      * Creates an array of unique values that is the
8580      * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8581      * of the given arrays. The order of result values is determined by the order
8582      * they occur in the arrays.
8583      *
8584      * @static
8585      * @memberOf _
8586      * @since 2.4.0
8587      * @category Array
8588      * @param {...Array} [arrays] The arrays to inspect.
8589      * @returns {Array} Returns the new array of filtered values.
8590      * @see _.difference, _.without
8591      * @example
8592      *
8593      * _.xor([2, 1], [2, 3]);
8594      * // => [1, 3]
8595      */
8596     var xor = baseRest(function(arrays) {
8597       return baseXor(arrayFilter(arrays, isArrayLikeObject));
8598     });
8599
8600     /**
8601      * This method is like `_.xor` except that it accepts `iteratee` which is
8602      * invoked for each element of each `arrays` to generate the criterion by
8603      * which by which they're compared. The order of result values is determined
8604      * by the order they occur in the arrays. The iteratee is invoked with one
8605      * argument: (value).
8606      *
8607      * @static
8608      * @memberOf _
8609      * @since 4.0.0
8610      * @category Array
8611      * @param {...Array} [arrays] The arrays to inspect.
8612      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8613      * @returns {Array} Returns the new array of filtered values.
8614      * @example
8615      *
8616      * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8617      * // => [1.2, 3.4]
8618      *
8619      * // The `_.property` iteratee shorthand.
8620      * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8621      * // => [{ 'x': 2 }]
8622      */
8623     var xorBy = baseRest(function(arrays) {
8624       var iteratee = last(arrays);
8625       if (isArrayLikeObject(iteratee)) {
8626         iteratee = undefined;
8627       }
8628       return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8629     });
8630
8631     /**
8632      * This method is like `_.xor` except that it accepts `comparator` which is
8633      * invoked to compare elements of `arrays`. The order of result values is
8634      * determined by the order they occur in the arrays. The comparator is invoked
8635      * with two arguments: (arrVal, othVal).
8636      *
8637      * @static
8638      * @memberOf _
8639      * @since 4.0.0
8640      * @category Array
8641      * @param {...Array} [arrays] The arrays to inspect.
8642      * @param {Function} [comparator] The comparator invoked per element.
8643      * @returns {Array} Returns the new array of filtered values.
8644      * @example
8645      *
8646      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8647      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8648      *
8649      * _.xorWith(objects, others, _.isEqual);
8650      * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8651      */
8652     var xorWith = baseRest(function(arrays) {
8653       var comparator = last(arrays);
8654       comparator = typeof comparator == 'function' ? comparator : undefined;
8655       return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8656     });
8657
8658     /**
8659      * Creates an array of grouped elements, the first of which contains the
8660      * first elements of the given arrays, the second of which contains the
8661      * second elements of the given arrays, and so on.
8662      *
8663      * @static
8664      * @memberOf _
8665      * @since 0.1.0
8666      * @category Array
8667      * @param {...Array} [arrays] The arrays to process.
8668      * @returns {Array} Returns the new array of grouped elements.
8669      * @example
8670      *
8671      * _.zip(['a', 'b'], [1, 2], [true, false]);
8672      * // => [['a', 1, true], ['b', 2, false]]
8673      */
8674     var zip = baseRest(unzip);
8675
8676     /**
8677      * This method is like `_.fromPairs` except that it accepts two arrays,
8678      * one of property identifiers and one of corresponding values.
8679      *
8680      * @static
8681      * @memberOf _
8682      * @since 0.4.0
8683      * @category Array
8684      * @param {Array} [props=[]] The property identifiers.
8685      * @param {Array} [values=[]] The property values.
8686      * @returns {Object} Returns the new object.
8687      * @example
8688      *
8689      * _.zipObject(['a', 'b'], [1, 2]);
8690      * // => { 'a': 1, 'b': 2 }
8691      */
8692     function zipObject(props, values) {
8693       return baseZipObject(props || [], values || [], assignValue);
8694     }
8695
8696     /**
8697      * This method is like `_.zipObject` except that it supports property paths.
8698      *
8699      * @static
8700      * @memberOf _
8701      * @since 4.1.0
8702      * @category Array
8703      * @param {Array} [props=[]] The property identifiers.
8704      * @param {Array} [values=[]] The property values.
8705      * @returns {Object} Returns the new object.
8706      * @example
8707      *
8708      * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8709      * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8710      */
8711     function zipObjectDeep(props, values) {
8712       return baseZipObject(props || [], values || [], baseSet);
8713     }
8714
8715     /**
8716      * This method is like `_.zip` except that it accepts `iteratee` to specify
8717      * how grouped values should be combined. The iteratee is invoked with the
8718      * elements of each group: (...group).
8719      *
8720      * @static
8721      * @memberOf _
8722      * @since 3.8.0
8723      * @category Array
8724      * @param {...Array} [arrays] The arrays to process.
8725      * @param {Function} [iteratee=_.identity] The function to combine
8726      *  grouped values.
8727      * @returns {Array} Returns the new array of grouped elements.
8728      * @example
8729      *
8730      * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8731      *   return a + b + c;
8732      * });
8733      * // => [111, 222]
8734      */
8735     var zipWith = baseRest(function(arrays) {
8736       var length = arrays.length,
8737           iteratee = length > 1 ? arrays[length - 1] : undefined;
8738
8739       iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8740       return unzipWith(arrays, iteratee);
8741     });
8742
8743     /*------------------------------------------------------------------------*/
8744
8745     /**
8746      * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8747      * chain sequences enabled. The result of such sequences must be unwrapped
8748      * with `_#value`.
8749      *
8750      * @static
8751      * @memberOf _
8752      * @since 1.3.0
8753      * @category Seq
8754      * @param {*} value The value to wrap.
8755      * @returns {Object} Returns the new `lodash` wrapper instance.
8756      * @example
8757      *
8758      * var users = [
8759      *   { 'user': 'barney',  'age': 36 },
8760      *   { 'user': 'fred',    'age': 40 },
8761      *   { 'user': 'pebbles', 'age': 1 }
8762      * ];
8763      *
8764      * var youngest = _
8765      *   .chain(users)
8766      *   .sortBy('age')
8767      *   .map(function(o) {
8768      *     return o.user + ' is ' + o.age;
8769      *   })
8770      *   .head()
8771      *   .value();
8772      * // => 'pebbles is 1'
8773      */
8774     function chain(value) {
8775       var result = lodash(value);
8776       result.__chain__ = true;
8777       return result;
8778     }
8779
8780     /**
8781      * This method invokes `interceptor` and returns `value`. The interceptor
8782      * is invoked with one argument; (value). The purpose of this method is to
8783      * "tap into" a method chain sequence in order to modify intermediate results.
8784      *
8785      * @static
8786      * @memberOf _
8787      * @since 0.1.0
8788      * @category Seq
8789      * @param {*} value The value to provide to `interceptor`.
8790      * @param {Function} interceptor The function to invoke.
8791      * @returns {*} Returns `value`.
8792      * @example
8793      *
8794      * _([1, 2, 3])
8795      *  .tap(function(array) {
8796      *    // Mutate input array.
8797      *    array.pop();
8798      *  })
8799      *  .reverse()
8800      *  .value();
8801      * // => [2, 1]
8802      */
8803     function tap(value, interceptor) {
8804       interceptor(value);
8805       return value;
8806     }
8807
8808     /**
8809      * This method is like `_.tap` except that it returns the result of `interceptor`.
8810      * The purpose of this method is to "pass thru" values replacing intermediate
8811      * results in a method chain sequence.
8812      *
8813      * @static
8814      * @memberOf _
8815      * @since 3.0.0
8816      * @category Seq
8817      * @param {*} value The value to provide to `interceptor`.
8818      * @param {Function} interceptor The function to invoke.
8819      * @returns {*} Returns the result of `interceptor`.
8820      * @example
8821      *
8822      * _('  abc  ')
8823      *  .chain()
8824      *  .trim()
8825      *  .thru(function(value) {
8826      *    return [value];
8827      *  })
8828      *  .value();
8829      * // => ['abc']
8830      */
8831     function thru(value, interceptor) {
8832       return interceptor(value);
8833     }
8834
8835     /**
8836      * This method is the wrapper version of `_.at`.
8837      *
8838      * @name at
8839      * @memberOf _
8840      * @since 1.0.0
8841      * @category Seq
8842      * @param {...(string|string[])} [paths] The property paths to pick.
8843      * @returns {Object} Returns the new `lodash` wrapper instance.
8844      * @example
8845      *
8846      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8847      *
8848      * _(object).at(['a[0].b.c', 'a[1]']).value();
8849      * // => [3, 4]
8850      */
8851     var wrapperAt = flatRest(function(paths) {
8852       var length = paths.length,
8853           start = length ? paths[0] : 0,
8854           value = this.__wrapped__,
8855           interceptor = function(object) { return baseAt(object, paths); };
8856
8857       if (length > 1 || this.__actions__.length ||
8858           !(value instanceof LazyWrapper) || !isIndex(start)) {
8859         return this.thru(interceptor);
8860       }
8861       value = value.slice(start, +start + (length ? 1 : 0));
8862       value.__actions__.push({
8863         'func': thru,
8864         'args': [interceptor],
8865         'thisArg': undefined
8866       });
8867       return new LodashWrapper(value, this.__chain__).thru(function(array) {
8868         if (length && !array.length) {
8869           array.push(undefined);
8870         }
8871         return array;
8872       });
8873     });
8874
8875     /**
8876      * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8877      *
8878      * @name chain
8879      * @memberOf _
8880      * @since 0.1.0
8881      * @category Seq
8882      * @returns {Object} Returns the new `lodash` wrapper instance.
8883      * @example
8884      *
8885      * var users = [
8886      *   { 'user': 'barney', 'age': 36 },
8887      *   { 'user': 'fred',   'age': 40 }
8888      * ];
8889      *
8890      * // A sequence without explicit chaining.
8891      * _(users).head();
8892      * // => { 'user': 'barney', 'age': 36 }
8893      *
8894      * // A sequence with explicit chaining.
8895      * _(users)
8896      *   .chain()
8897      *   .head()
8898      *   .pick('user')
8899      *   .value();
8900      * // => { 'user': 'barney' }
8901      */
8902     function wrapperChain() {
8903       return chain(this);
8904     }
8905
8906     /**
8907      * Executes the chain sequence and returns the wrapped result.
8908      *
8909      * @name commit
8910      * @memberOf _
8911      * @since 3.2.0
8912      * @category Seq
8913      * @returns {Object} Returns the new `lodash` wrapper instance.
8914      * @example
8915      *
8916      * var array = [1, 2];
8917      * var wrapped = _(array).push(3);
8918      *
8919      * console.log(array);
8920      * // => [1, 2]
8921      *
8922      * wrapped = wrapped.commit();
8923      * console.log(array);
8924      * // => [1, 2, 3]
8925      *
8926      * wrapped.last();
8927      * // => 3
8928      *
8929      * console.log(array);
8930      * // => [1, 2, 3]
8931      */
8932     function wrapperCommit() {
8933       return new LodashWrapper(this.value(), this.__chain__);
8934     }
8935
8936     /**
8937      * Gets the next value on a wrapped object following the
8938      * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8939      *
8940      * @name next
8941      * @memberOf _
8942      * @since 4.0.0
8943      * @category Seq
8944      * @returns {Object} Returns the next iterator value.
8945      * @example
8946      *
8947      * var wrapped = _([1, 2]);
8948      *
8949      * wrapped.next();
8950      * // => { 'done': false, 'value': 1 }
8951      *
8952      * wrapped.next();
8953      * // => { 'done': false, 'value': 2 }
8954      *
8955      * wrapped.next();
8956      * // => { 'done': true, 'value': undefined }
8957      */
8958     function wrapperNext() {
8959       if (this.__values__ === undefined) {
8960         this.__values__ = toArray(this.value());
8961       }
8962       var done = this.__index__ >= this.__values__.length,
8963           value = done ? undefined : this.__values__[this.__index__++];
8964
8965       return { 'done': done, 'value': value };
8966     }
8967
8968     /**
8969      * Enables the wrapper to be iterable.
8970      *
8971      * @name Symbol.iterator
8972      * @memberOf _
8973      * @since 4.0.0
8974      * @category Seq
8975      * @returns {Object} Returns the wrapper object.
8976      * @example
8977      *
8978      * var wrapped = _([1, 2]);
8979      *
8980      * wrapped[Symbol.iterator]() === wrapped;
8981      * // => true
8982      *
8983      * Array.from(wrapped);
8984      * // => [1, 2]
8985      */
8986     function wrapperToIterator() {
8987       return this;
8988     }
8989
8990     /**
8991      * Creates a clone of the chain sequence planting `value` as the wrapped value.
8992      *
8993      * @name plant
8994      * @memberOf _
8995      * @since 3.2.0
8996      * @category Seq
8997      * @param {*} value The value to plant.
8998      * @returns {Object} Returns the new `lodash` wrapper instance.
8999      * @example
9000      *
9001      * function square(n) {
9002      *   return n * n;
9003      * }
9004      *
9005      * var wrapped = _([1, 2]).map(square);
9006      * var other = wrapped.plant([3, 4]);
9007      *
9008      * other.value();
9009      * // => [9, 16]
9010      *
9011      * wrapped.value();
9012      * // => [1, 4]
9013      */
9014     function wrapperPlant(value) {
9015       var result,
9016           parent = this;
9017
9018       while (parent instanceof baseLodash) {
9019         var clone = wrapperClone(parent);
9020         clone.__index__ = 0;
9021         clone.__values__ = undefined;
9022         if (result) {
9023           previous.__wrapped__ = clone;
9024         } else {
9025           result = clone;
9026         }
9027         var previous = clone;
9028         parent = parent.__wrapped__;
9029       }
9030       previous.__wrapped__ = value;
9031       return result;
9032     }
9033
9034     /**
9035      * This method is the wrapper version of `_.reverse`.
9036      *
9037      * **Note:** This method mutates the wrapped array.
9038      *
9039      * @name reverse
9040      * @memberOf _
9041      * @since 0.1.0
9042      * @category Seq
9043      * @returns {Object} Returns the new `lodash` wrapper instance.
9044      * @example
9045      *
9046      * var array = [1, 2, 3];
9047      *
9048      * _(array).reverse().value()
9049      * // => [3, 2, 1]
9050      *
9051      * console.log(array);
9052      * // => [3, 2, 1]
9053      */
9054     function wrapperReverse() {
9055       var value = this.__wrapped__;
9056       if (value instanceof LazyWrapper) {
9057         var wrapped = value;
9058         if (this.__actions__.length) {
9059           wrapped = new LazyWrapper(this);
9060         }
9061         wrapped = wrapped.reverse();
9062         wrapped.__actions__.push({
9063           'func': thru,
9064           'args': [reverse],
9065           'thisArg': undefined
9066         });
9067         return new LodashWrapper(wrapped, this.__chain__);
9068       }
9069       return this.thru(reverse);
9070     }
9071
9072     /**
9073      * Executes the chain sequence to resolve the unwrapped value.
9074      *
9075      * @name value
9076      * @memberOf _
9077      * @since 0.1.0
9078      * @alias toJSON, valueOf
9079      * @category Seq
9080      * @returns {*} Returns the resolved unwrapped value.
9081      * @example
9082      *
9083      * _([1, 2, 3]).value();
9084      * // => [1, 2, 3]
9085      */
9086     function wrapperValue() {
9087       return baseWrapperValue(this.__wrapped__, this.__actions__);
9088     }
9089
9090     /*------------------------------------------------------------------------*/
9091
9092     /**
9093      * Creates an object composed of keys generated from the results of running
9094      * each element of `collection` thru `iteratee`. The corresponding value of
9095      * each key is the number of times the key was returned by `iteratee`. The
9096      * iteratee is invoked with one argument: (value).
9097      *
9098      * @static
9099      * @memberOf _
9100      * @since 0.5.0
9101      * @category Collection
9102      * @param {Array|Object} collection The collection to iterate over.
9103      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9104      * @returns {Object} Returns the composed aggregate object.
9105      * @example
9106      *
9107      * _.countBy([6.1, 4.2, 6.3], Math.floor);
9108      * // => { '4': 1, '6': 2 }
9109      *
9110      * // The `_.property` iteratee shorthand.
9111      * _.countBy(['one', 'two', 'three'], 'length');
9112      * // => { '3': 2, '5': 1 }
9113      */
9114     var countBy = createAggregator(function(result, value, key) {
9115       if (hasOwnProperty.call(result, key)) {
9116         ++result[key];
9117       } else {
9118         baseAssignValue(result, key, 1);
9119       }
9120     });
9121
9122     /**
9123      * Checks if `predicate` returns truthy for **all** elements of `collection`.
9124      * Iteration is stopped once `predicate` returns falsey. The predicate is
9125      * invoked with three arguments: (value, index|key, collection).
9126      *
9127      * **Note:** This method returns `true` for
9128      * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9129      * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9130      * elements of empty collections.
9131      *
9132      * @static
9133      * @memberOf _
9134      * @since 0.1.0
9135      * @category Collection
9136      * @param {Array|Object} collection The collection to iterate over.
9137      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9138      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9139      * @returns {boolean} Returns `true` if all elements pass the predicate check,
9140      *  else `false`.
9141      * @example
9142      *
9143      * _.every([true, 1, null, 'yes'], Boolean);
9144      * // => false
9145      *
9146      * var users = [
9147      *   { 'user': 'barney', 'age': 36, 'active': false },
9148      *   { 'user': 'fred',   'age': 40, 'active': false }
9149      * ];
9150      *
9151      * // The `_.matches` iteratee shorthand.
9152      * _.every(users, { 'user': 'barney', 'active': false });
9153      * // => false
9154      *
9155      * // The `_.matchesProperty` iteratee shorthand.
9156      * _.every(users, ['active', false]);
9157      * // => true
9158      *
9159      * // The `_.property` iteratee shorthand.
9160      * _.every(users, 'active');
9161      * // => false
9162      */
9163     function every(collection, predicate, guard) {
9164       var func = isArray(collection) ? arrayEvery : baseEvery;
9165       if (guard && isIterateeCall(collection, predicate, guard)) {
9166         predicate = undefined;
9167       }
9168       return func(collection, getIteratee(predicate, 3));
9169     }
9170
9171     /**
9172      * Iterates over elements of `collection`, returning an array of all elements
9173      * `predicate` returns truthy for. The predicate is invoked with three
9174      * arguments: (value, index|key, collection).
9175      *
9176      * **Note:** Unlike `_.remove`, this method returns a new array.
9177      *
9178      * @static
9179      * @memberOf _
9180      * @since 0.1.0
9181      * @category Collection
9182      * @param {Array|Object} collection The collection to iterate over.
9183      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9184      * @returns {Array} Returns the new filtered array.
9185      * @see _.reject
9186      * @example
9187      *
9188      * var users = [
9189      *   { 'user': 'barney', 'age': 36, 'active': true },
9190      *   { 'user': 'fred',   'age': 40, 'active': false }
9191      * ];
9192      *
9193      * _.filter(users, function(o) { return !o.active; });
9194      * // => objects for ['fred']
9195      *
9196      * // The `_.matches` iteratee shorthand.
9197      * _.filter(users, { 'age': 36, 'active': true });
9198      * // => objects for ['barney']
9199      *
9200      * // The `_.matchesProperty` iteratee shorthand.
9201      * _.filter(users, ['active', false]);
9202      * // => objects for ['fred']
9203      *
9204      * // The `_.property` iteratee shorthand.
9205      * _.filter(users, 'active');
9206      * // => objects for ['barney']
9207      */
9208     function filter(collection, predicate) {
9209       var func = isArray(collection) ? arrayFilter : baseFilter;
9210       return func(collection, getIteratee(predicate, 3));
9211     }
9212
9213     /**
9214      * Iterates over elements of `collection`, returning the first element
9215      * `predicate` returns truthy for. The predicate is invoked with three
9216      * arguments: (value, index|key, collection).
9217      *
9218      * @static
9219      * @memberOf _
9220      * @since 0.1.0
9221      * @category Collection
9222      * @param {Array|Object} collection The collection to inspect.
9223      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9224      * @param {number} [fromIndex=0] The index to search from.
9225      * @returns {*} Returns the matched element, else `undefined`.
9226      * @example
9227      *
9228      * var users = [
9229      *   { 'user': 'barney',  'age': 36, 'active': true },
9230      *   { 'user': 'fred',    'age': 40, 'active': false },
9231      *   { 'user': 'pebbles', 'age': 1,  'active': true }
9232      * ];
9233      *
9234      * _.find(users, function(o) { return o.age < 40; });
9235      * // => object for 'barney'
9236      *
9237      * // The `_.matches` iteratee shorthand.
9238      * _.find(users, { 'age': 1, 'active': true });
9239      * // => object for 'pebbles'
9240      *
9241      * // The `_.matchesProperty` iteratee shorthand.
9242      * _.find(users, ['active', false]);
9243      * // => object for 'fred'
9244      *
9245      * // The `_.property` iteratee shorthand.
9246      * _.find(users, 'active');
9247      * // => object for 'barney'
9248      */
9249     var find = createFind(findIndex);
9250
9251     /**
9252      * This method is like `_.find` except that it iterates over elements of
9253      * `collection` from right to left.
9254      *
9255      * @static
9256      * @memberOf _
9257      * @since 2.0.0
9258      * @category Collection
9259      * @param {Array|Object} collection The collection to inspect.
9260      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9261      * @param {number} [fromIndex=collection.length-1] The index to search from.
9262      * @returns {*} Returns the matched element, else `undefined`.
9263      * @example
9264      *
9265      * _.findLast([1, 2, 3, 4], function(n) {
9266      *   return n % 2 == 1;
9267      * });
9268      * // => 3
9269      */
9270     var findLast = createFind(findLastIndex);
9271
9272     /**
9273      * Creates a flattened array of values by running each element in `collection`
9274      * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9275      * with three arguments: (value, index|key, collection).
9276      *
9277      * @static
9278      * @memberOf _
9279      * @since 4.0.0
9280      * @category Collection
9281      * @param {Array|Object} collection The collection to iterate over.
9282      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9283      * @returns {Array} Returns the new flattened array.
9284      * @example
9285      *
9286      * function duplicate(n) {
9287      *   return [n, n];
9288      * }
9289      *
9290      * _.flatMap([1, 2], duplicate);
9291      * // => [1, 1, 2, 2]
9292      */
9293     function flatMap(collection, iteratee) {
9294       return baseFlatten(map(collection, iteratee), 1);
9295     }
9296
9297     /**
9298      * This method is like `_.flatMap` except that it recursively flattens the
9299      * mapped results.
9300      *
9301      * @static
9302      * @memberOf _
9303      * @since 4.7.0
9304      * @category Collection
9305      * @param {Array|Object} collection The collection to iterate over.
9306      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9307      * @returns {Array} Returns the new flattened array.
9308      * @example
9309      *
9310      * function duplicate(n) {
9311      *   return [[[n, n]]];
9312      * }
9313      *
9314      * _.flatMapDeep([1, 2], duplicate);
9315      * // => [1, 1, 2, 2]
9316      */
9317     function flatMapDeep(collection, iteratee) {
9318       return baseFlatten(map(collection, iteratee), INFINITY);
9319     }
9320
9321     /**
9322      * This method is like `_.flatMap` except that it recursively flattens the
9323      * mapped results up to `depth` times.
9324      *
9325      * @static
9326      * @memberOf _
9327      * @since 4.7.0
9328      * @category Collection
9329      * @param {Array|Object} collection The collection to iterate over.
9330      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9331      * @param {number} [depth=1] The maximum recursion depth.
9332      * @returns {Array} Returns the new flattened array.
9333      * @example
9334      *
9335      * function duplicate(n) {
9336      *   return [[[n, n]]];
9337      * }
9338      *
9339      * _.flatMapDepth([1, 2], duplicate, 2);
9340      * // => [[1, 1], [2, 2]]
9341      */
9342     function flatMapDepth(collection, iteratee, depth) {
9343       depth = depth === undefined ? 1 : toInteger(depth);
9344       return baseFlatten(map(collection, iteratee), depth);
9345     }
9346
9347     /**
9348      * Iterates over elements of `collection` and invokes `iteratee` for each element.
9349      * The iteratee is invoked with three arguments: (value, index|key, collection).
9350      * Iteratee functions may exit iteration early by explicitly returning `false`.
9351      *
9352      * **Note:** As with other "Collections" methods, objects with a "length"
9353      * property are iterated like arrays. To avoid this behavior use `_.forIn`
9354      * or `_.forOwn` for object iteration.
9355      *
9356      * @static
9357      * @memberOf _
9358      * @since 0.1.0
9359      * @alias each
9360      * @category Collection
9361      * @param {Array|Object} collection The collection to iterate over.
9362      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9363      * @returns {Array|Object} Returns `collection`.
9364      * @see _.forEachRight
9365      * @example
9366      *
9367      * _.forEach([1, 2], function(value) {
9368      *   console.log(value);
9369      * });
9370      * // => Logs `1` then `2`.
9371      *
9372      * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9373      *   console.log(key);
9374      * });
9375      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9376      */
9377     function forEach(collection, iteratee) {
9378       var func = isArray(collection) ? arrayEach : baseEach;
9379       return func(collection, getIteratee(iteratee, 3));
9380     }
9381
9382     /**
9383      * This method is like `_.forEach` except that it iterates over elements of
9384      * `collection` from right to left.
9385      *
9386      * @static
9387      * @memberOf _
9388      * @since 2.0.0
9389      * @alias eachRight
9390      * @category Collection
9391      * @param {Array|Object} collection The collection to iterate over.
9392      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9393      * @returns {Array|Object} Returns `collection`.
9394      * @see _.forEach
9395      * @example
9396      *
9397      * _.forEachRight([1, 2], function(value) {
9398      *   console.log(value);
9399      * });
9400      * // => Logs `2` then `1`.
9401      */
9402     function forEachRight(collection, iteratee) {
9403       var func = isArray(collection) ? arrayEachRight : baseEachRight;
9404       return func(collection, getIteratee(iteratee, 3));
9405     }
9406
9407     /**
9408      * Creates an object composed of keys generated from the results of running
9409      * each element of `collection` thru `iteratee`. The order of grouped values
9410      * is determined by the order they occur in `collection`. The corresponding
9411      * value of each key is an array of elements responsible for generating the
9412      * key. The iteratee is invoked with one argument: (value).
9413      *
9414      * @static
9415      * @memberOf _
9416      * @since 0.1.0
9417      * @category Collection
9418      * @param {Array|Object} collection The collection to iterate over.
9419      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9420      * @returns {Object} Returns the composed aggregate object.
9421      * @example
9422      *
9423      * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9424      * // => { '4': [4.2], '6': [6.1, 6.3] }
9425      *
9426      * // The `_.property` iteratee shorthand.
9427      * _.groupBy(['one', 'two', 'three'], 'length');
9428      * // => { '3': ['one', 'two'], '5': ['three'] }
9429      */
9430     var groupBy = createAggregator(function(result, value, key) {
9431       if (hasOwnProperty.call(result, key)) {
9432         result[key].push(value);
9433       } else {
9434         baseAssignValue(result, key, [value]);
9435       }
9436     });
9437
9438     /**
9439      * Checks if `value` is in `collection`. If `collection` is a string, it's
9440      * checked for a substring of `value`, otherwise
9441      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9442      * is used for equality comparisons. If `fromIndex` is negative, it's used as
9443      * the offset from the end of `collection`.
9444      *
9445      * @static
9446      * @memberOf _
9447      * @since 0.1.0
9448      * @category Collection
9449      * @param {Array|Object|string} collection The collection to inspect.
9450      * @param {*} value The value to search for.
9451      * @param {number} [fromIndex=0] The index to search from.
9452      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9453      * @returns {boolean} Returns `true` if `value` is found, else `false`.
9454      * @example
9455      *
9456      * _.includes([1, 2, 3], 1);
9457      * // => true
9458      *
9459      * _.includes([1, 2, 3], 1, 2);
9460      * // => false
9461      *
9462      * _.includes({ 'a': 1, 'b': 2 }, 1);
9463      * // => true
9464      *
9465      * _.includes('abcd', 'bc');
9466      * // => true
9467      */
9468     function includes(collection, value, fromIndex, guard) {
9469       collection = isArrayLike(collection) ? collection : values(collection);
9470       fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9471
9472       var length = collection.length;
9473       if (fromIndex < 0) {
9474         fromIndex = nativeMax(length + fromIndex, 0);
9475       }
9476       return isString(collection)
9477         ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9478         : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9479     }
9480
9481     /**
9482      * Invokes the method at `path` of each element in `collection`, returning
9483      * an array of the results of each invoked method. Any additional arguments
9484      * are provided to each invoked method. If `path` is a function, it's invoked
9485      * for, and `this` bound to, each element in `collection`.
9486      *
9487      * @static
9488      * @memberOf _
9489      * @since 4.0.0
9490      * @category Collection
9491      * @param {Array|Object} collection The collection to iterate over.
9492      * @param {Array|Function|string} path The path of the method to invoke or
9493      *  the function invoked per iteration.
9494      * @param {...*} [args] The arguments to invoke each method with.
9495      * @returns {Array} Returns the array of results.
9496      * @example
9497      *
9498      * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9499      * // => [[1, 5, 7], [1, 2, 3]]
9500      *
9501      * _.invokeMap([123, 456], String.prototype.split, '');
9502      * // => [['1', '2', '3'], ['4', '5', '6']]
9503      */
9504     var invokeMap = baseRest(function(collection, path, args) {
9505       var index = -1,
9506           isFunc = typeof path == 'function',
9507           result = isArrayLike(collection) ? Array(collection.length) : [];
9508
9509       baseEach(collection, function(value) {
9510         result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
9511       });
9512       return result;
9513     });
9514
9515     /**
9516      * Creates an object composed of keys generated from the results of running
9517      * each element of `collection` thru `iteratee`. The corresponding value of
9518      * each key is the last element responsible for generating the key. The
9519      * iteratee is invoked with one argument: (value).
9520      *
9521      * @static
9522      * @memberOf _
9523      * @since 4.0.0
9524      * @category Collection
9525      * @param {Array|Object} collection The collection to iterate over.
9526      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9527      * @returns {Object} Returns the composed aggregate object.
9528      * @example
9529      *
9530      * var array = [
9531      *   { 'dir': 'left', 'code': 97 },
9532      *   { 'dir': 'right', 'code': 100 }
9533      * ];
9534      *
9535      * _.keyBy(array, function(o) {
9536      *   return String.fromCharCode(o.code);
9537      * });
9538      * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9539      *
9540      * _.keyBy(array, 'dir');
9541      * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9542      */
9543     var keyBy = createAggregator(function(result, value, key) {
9544       baseAssignValue(result, key, value);
9545     });
9546
9547     /**
9548      * Creates an array of values by running each element in `collection` thru
9549      * `iteratee`. The iteratee is invoked with three arguments:
9550      * (value, index|key, collection).
9551      *
9552      * Many lodash methods are guarded to work as iteratees for methods like
9553      * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9554      *
9555      * The guarded methods are:
9556      * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9557      * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9558      * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9559      * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9560      *
9561      * @static
9562      * @memberOf _
9563      * @since 0.1.0
9564      * @category Collection
9565      * @param {Array|Object} collection The collection to iterate over.
9566      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9567      * @returns {Array} Returns the new mapped array.
9568      * @example
9569      *
9570      * function square(n) {
9571      *   return n * n;
9572      * }
9573      *
9574      * _.map([4, 8], square);
9575      * // => [16, 64]
9576      *
9577      * _.map({ 'a': 4, 'b': 8 }, square);
9578      * // => [16, 64] (iteration order is not guaranteed)
9579      *
9580      * var users = [
9581      *   { 'user': 'barney' },
9582      *   { 'user': 'fred' }
9583      * ];
9584      *
9585      * // The `_.property` iteratee shorthand.
9586      * _.map(users, 'user');
9587      * // => ['barney', 'fred']
9588      */
9589     function map(collection, iteratee) {
9590       var func = isArray(collection) ? arrayMap : baseMap;
9591       return func(collection, getIteratee(iteratee, 3));
9592     }
9593
9594     /**
9595      * This method is like `_.sortBy` except that it allows specifying the sort
9596      * orders of the iteratees to sort by. If `orders` is unspecified, all values
9597      * are sorted in ascending order. Otherwise, specify an order of "desc" for
9598      * descending or "asc" for ascending sort order of corresponding values.
9599      *
9600      * @static
9601      * @memberOf _
9602      * @since 4.0.0
9603      * @category Collection
9604      * @param {Array|Object} collection The collection to iterate over.
9605      * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9606      *  The iteratees to sort by.
9607      * @param {string[]} [orders] The sort orders of `iteratees`.
9608      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9609      * @returns {Array} Returns the new sorted array.
9610      * @example
9611      *
9612      * var users = [
9613      *   { 'user': 'fred',   'age': 48 },
9614      *   { 'user': 'barney', 'age': 34 },
9615      *   { 'user': 'fred',   'age': 40 },
9616      *   { 'user': 'barney', 'age': 36 }
9617      * ];
9618      *
9619      * // Sort by `user` in ascending order and by `age` in descending order.
9620      * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9621      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9622      */
9623     function orderBy(collection, iteratees, orders, guard) {
9624       if (collection == null) {
9625         return [];
9626       }
9627       if (!isArray(iteratees)) {
9628         iteratees = iteratees == null ? [] : [iteratees];
9629       }
9630       orders = guard ? undefined : orders;
9631       if (!isArray(orders)) {
9632         orders = orders == null ? [] : [orders];
9633       }
9634       return baseOrderBy(collection, iteratees, orders);
9635     }
9636
9637     /**
9638      * Creates an array of elements split into two groups, the first of which
9639      * contains elements `predicate` returns truthy for, the second of which
9640      * contains elements `predicate` returns falsey for. The predicate is
9641      * invoked with one argument: (value).
9642      *
9643      * @static
9644      * @memberOf _
9645      * @since 3.0.0
9646      * @category Collection
9647      * @param {Array|Object} collection The collection to iterate over.
9648      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9649      * @returns {Array} Returns the array of grouped elements.
9650      * @example
9651      *
9652      * var users = [
9653      *   { 'user': 'barney',  'age': 36, 'active': false },
9654      *   { 'user': 'fred',    'age': 40, 'active': true },
9655      *   { 'user': 'pebbles', 'age': 1,  'active': false }
9656      * ];
9657      *
9658      * _.partition(users, function(o) { return o.active; });
9659      * // => objects for [['fred'], ['barney', 'pebbles']]
9660      *
9661      * // The `_.matches` iteratee shorthand.
9662      * _.partition(users, { 'age': 1, 'active': false });
9663      * // => objects for [['pebbles'], ['barney', 'fred']]
9664      *
9665      * // The `_.matchesProperty` iteratee shorthand.
9666      * _.partition(users, ['active', false]);
9667      * // => objects for [['barney', 'pebbles'], ['fred']]
9668      *
9669      * // The `_.property` iteratee shorthand.
9670      * _.partition(users, 'active');
9671      * // => objects for [['fred'], ['barney', 'pebbles']]
9672      */
9673     var partition = createAggregator(function(result, value, key) {
9674       result[key ? 0 : 1].push(value);
9675     }, function() { return [[], []]; });
9676
9677     /**
9678      * Reduces `collection` to a value which is the accumulated result of running
9679      * each element in `collection` thru `iteratee`, where each successive
9680      * invocation is supplied the return value of the previous. If `accumulator`
9681      * is not given, the first element of `collection` is used as the initial
9682      * value. The iteratee is invoked with four arguments:
9683      * (accumulator, value, index|key, collection).
9684      *
9685      * Many lodash methods are guarded to work as iteratees for methods like
9686      * `_.reduce`, `_.reduceRight`, and `_.transform`.
9687      *
9688      * The guarded methods are:
9689      * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9690      * and `sortBy`
9691      *
9692      * @static
9693      * @memberOf _
9694      * @since 0.1.0
9695      * @category Collection
9696      * @param {Array|Object} collection The collection to iterate over.
9697      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9698      * @param {*} [accumulator] The initial value.
9699      * @returns {*} Returns the accumulated value.
9700      * @see _.reduceRight
9701      * @example
9702      *
9703      * _.reduce([1, 2], function(sum, n) {
9704      *   return sum + n;
9705      * }, 0);
9706      * // => 3
9707      *
9708      * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9709      *   (result[value] || (result[value] = [])).push(key);
9710      *   return result;
9711      * }, {});
9712      * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9713      */
9714     function reduce(collection, iteratee, accumulator) {
9715       var func = isArray(collection) ? arrayReduce : baseReduce,
9716           initAccum = arguments.length < 3;
9717
9718       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9719     }
9720
9721     /**
9722      * This method is like `_.reduce` except that it iterates over elements of
9723      * `collection` from right to left.
9724      *
9725      * @static
9726      * @memberOf _
9727      * @since 0.1.0
9728      * @category Collection
9729      * @param {Array|Object} collection The collection to iterate over.
9730      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9731      * @param {*} [accumulator] The initial value.
9732      * @returns {*} Returns the accumulated value.
9733      * @see _.reduce
9734      * @example
9735      *
9736      * var array = [[0, 1], [2, 3], [4, 5]];
9737      *
9738      * _.reduceRight(array, function(flattened, other) {
9739      *   return flattened.concat(other);
9740      * }, []);
9741      * // => [4, 5, 2, 3, 0, 1]
9742      */
9743     function reduceRight(collection, iteratee, accumulator) {
9744       var func = isArray(collection) ? arrayReduceRight : baseReduce,
9745           initAccum = arguments.length < 3;
9746
9747       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9748     }
9749
9750     /**
9751      * The opposite of `_.filter`; this method returns the elements of `collection`
9752      * that `predicate` does **not** return truthy for.
9753      *
9754      * @static
9755      * @memberOf _
9756      * @since 0.1.0
9757      * @category Collection
9758      * @param {Array|Object} collection The collection to iterate over.
9759      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9760      * @returns {Array} Returns the new filtered array.
9761      * @see _.filter
9762      * @example
9763      *
9764      * var users = [
9765      *   { 'user': 'barney', 'age': 36, 'active': false },
9766      *   { 'user': 'fred',   'age': 40, 'active': true }
9767      * ];
9768      *
9769      * _.reject(users, function(o) { return !o.active; });
9770      * // => objects for ['fred']
9771      *
9772      * // The `_.matches` iteratee shorthand.
9773      * _.reject(users, { 'age': 40, 'active': true });
9774      * // => objects for ['barney']
9775      *
9776      * // The `_.matchesProperty` iteratee shorthand.
9777      * _.reject(users, ['active', false]);
9778      * // => objects for ['fred']
9779      *
9780      * // The `_.property` iteratee shorthand.
9781      * _.reject(users, 'active');
9782      * // => objects for ['barney']
9783      */
9784     function reject(collection, predicate) {
9785       var func = isArray(collection) ? arrayFilter : baseFilter;
9786       return func(collection, negate(getIteratee(predicate, 3)));
9787     }
9788
9789     /**
9790      * Gets a random element from `collection`.
9791      *
9792      * @static
9793      * @memberOf _
9794      * @since 2.0.0
9795      * @category Collection
9796      * @param {Array|Object} collection The collection to sample.
9797      * @returns {*} Returns the random element.
9798      * @example
9799      *
9800      * _.sample([1, 2, 3, 4]);
9801      * // => 2
9802      */
9803     function sample(collection) {
9804       var func = isArray(collection) ? arraySample : baseSample;
9805       return func(collection);
9806     }
9807
9808     /**
9809      * Gets `n` random elements at unique keys from `collection` up to the
9810      * size of `collection`.
9811      *
9812      * @static
9813      * @memberOf _
9814      * @since 4.0.0
9815      * @category Collection
9816      * @param {Array|Object} collection The collection to sample.
9817      * @param {number} [n=1] The number of elements to sample.
9818      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9819      * @returns {Array} Returns the random elements.
9820      * @example
9821      *
9822      * _.sampleSize([1, 2, 3], 2);
9823      * // => [3, 1]
9824      *
9825      * _.sampleSize([1, 2, 3], 4);
9826      * // => [2, 3, 1]
9827      */
9828     function sampleSize(collection, n, guard) {
9829       if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9830         n = 1;
9831       } else {
9832         n = toInteger(n);
9833       }
9834       var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9835       return func(collection, n);
9836     }
9837
9838     /**
9839      * Creates an array of shuffled values, using a version of the
9840      * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9841      *
9842      * @static
9843      * @memberOf _
9844      * @since 0.1.0
9845      * @category Collection
9846      * @param {Array|Object} collection The collection to shuffle.
9847      * @returns {Array} Returns the new shuffled array.
9848      * @example
9849      *
9850      * _.shuffle([1, 2, 3, 4]);
9851      * // => [4, 1, 3, 2]
9852      */
9853     function shuffle(collection) {
9854       var func = isArray(collection) ? arrayShuffle : baseShuffle;
9855       return func(collection);
9856     }
9857
9858     /**
9859      * Gets the size of `collection` by returning its length for array-like
9860      * values or the number of own enumerable string keyed properties for objects.
9861      *
9862      * @static
9863      * @memberOf _
9864      * @since 0.1.0
9865      * @category Collection
9866      * @param {Array|Object|string} collection The collection to inspect.
9867      * @returns {number} Returns the collection size.
9868      * @example
9869      *
9870      * _.size([1, 2, 3]);
9871      * // => 3
9872      *
9873      * _.size({ 'a': 1, 'b': 2 });
9874      * // => 2
9875      *
9876      * _.size('pebbles');
9877      * // => 7
9878      */
9879     function size(collection) {
9880       if (collection == null) {
9881         return 0;
9882       }
9883       if (isArrayLike(collection)) {
9884         return isString(collection) ? stringSize(collection) : collection.length;
9885       }
9886       var tag = getTag(collection);
9887       if (tag == mapTag || tag == setTag) {
9888         return collection.size;
9889       }
9890       return baseKeys(collection).length;
9891     }
9892
9893     /**
9894      * Checks if `predicate` returns truthy for **any** element of `collection`.
9895      * Iteration is stopped once `predicate` returns truthy. The predicate is
9896      * invoked with three arguments: (value, index|key, collection).
9897      *
9898      * @static
9899      * @memberOf _
9900      * @since 0.1.0
9901      * @category Collection
9902      * @param {Array|Object} collection The collection to iterate over.
9903      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9904      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9905      * @returns {boolean} Returns `true` if any element passes the predicate check,
9906      *  else `false`.
9907      * @example
9908      *
9909      * _.some([null, 0, 'yes', false], Boolean);
9910      * // => true
9911      *
9912      * var users = [
9913      *   { 'user': 'barney', 'active': true },
9914      *   { 'user': 'fred',   'active': false }
9915      * ];
9916      *
9917      * // The `_.matches` iteratee shorthand.
9918      * _.some(users, { 'user': 'barney', 'active': false });
9919      * // => false
9920      *
9921      * // The `_.matchesProperty` iteratee shorthand.
9922      * _.some(users, ['active', false]);
9923      * // => true
9924      *
9925      * // The `_.property` iteratee shorthand.
9926      * _.some(users, 'active');
9927      * // => true
9928      */
9929     function some(collection, predicate, guard) {
9930       var func = isArray(collection) ? arraySome : baseSome;
9931       if (guard && isIterateeCall(collection, predicate, guard)) {
9932         predicate = undefined;
9933       }
9934       return func(collection, getIteratee(predicate, 3));
9935     }
9936
9937     /**
9938      * Creates an array of elements, sorted in ascending order by the results of
9939      * running each element in a collection thru each iteratee. This method
9940      * performs a stable sort, that is, it preserves the original sort order of
9941      * equal elements. The iteratees are invoked with one argument: (value).
9942      *
9943      * @static
9944      * @memberOf _
9945      * @since 0.1.0
9946      * @category Collection
9947      * @param {Array|Object} collection The collection to iterate over.
9948      * @param {...(Function|Function[])} [iteratees=[_.identity]]
9949      *  The iteratees to sort by.
9950      * @returns {Array} Returns the new sorted array.
9951      * @example
9952      *
9953      * var users = [
9954      *   { 'user': 'fred',   'age': 48 },
9955      *   { 'user': 'barney', 'age': 36 },
9956      *   { 'user': 'fred',   'age': 40 },
9957      *   { 'user': 'barney', 'age': 34 }
9958      * ];
9959      *
9960      * _.sortBy(users, [function(o) { return o.user; }]);
9961      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9962      *
9963      * _.sortBy(users, ['user', 'age']);
9964      * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9965      */
9966     var sortBy = baseRest(function(collection, iteratees) {
9967       if (collection == null) {
9968         return [];
9969       }
9970       var length = iteratees.length;
9971       if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9972         iteratees = [];
9973       } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9974         iteratees = [iteratees[0]];
9975       }
9976       return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9977     });
9978
9979     /*------------------------------------------------------------------------*/
9980
9981     /**
9982      * Gets the timestamp of the number of milliseconds that have elapsed since
9983      * the Unix epoch (1 January 1970 00:00:00 UTC).
9984      *
9985      * @static
9986      * @memberOf _
9987      * @since 2.4.0
9988      * @category Date
9989      * @returns {number} Returns the timestamp.
9990      * @example
9991      *
9992      * _.defer(function(stamp) {
9993      *   console.log(_.now() - stamp);
9994      * }, _.now());
9995      * // => Logs the number of milliseconds it took for the deferred invocation.
9996      */
9997     var now = ctxNow || function() {
9998       return root.Date.now();
9999     };
10000
10001     /*------------------------------------------------------------------------*/
10002
10003     /**
10004      * The opposite of `_.before`; this method creates a function that invokes
10005      * `func` once it's called `n` or more times.
10006      *
10007      * @static
10008      * @memberOf _
10009      * @since 0.1.0
10010      * @category Function
10011      * @param {number} n The number of calls before `func` is invoked.
10012      * @param {Function} func The function to restrict.
10013      * @returns {Function} Returns the new restricted function.
10014      * @example
10015      *
10016      * var saves = ['profile', 'settings'];
10017      *
10018      * var done = _.after(saves.length, function() {
10019      *   console.log('done saving!');
10020      * });
10021      *
10022      * _.forEach(saves, function(type) {
10023      *   asyncSave({ 'type': type, 'complete': done });
10024      * });
10025      * // => Logs 'done saving!' after the two async saves have completed.
10026      */
10027     function after(n, func) {
10028       if (typeof func != 'function') {
10029         throw new TypeError(FUNC_ERROR_TEXT);
10030       }
10031       n = toInteger(n);
10032       return function() {
10033         if (--n < 1) {
10034           return func.apply(this, arguments);
10035         }
10036       };
10037     }
10038
10039     /**
10040      * Creates a function that invokes `func`, with up to `n` arguments,
10041      * ignoring any additional arguments.
10042      *
10043      * @static
10044      * @memberOf _
10045      * @since 3.0.0
10046      * @category Function
10047      * @param {Function} func The function to cap arguments for.
10048      * @param {number} [n=func.length] The arity cap.
10049      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10050      * @returns {Function} Returns the new capped function.
10051      * @example
10052      *
10053      * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10054      * // => [6, 8, 10]
10055      */
10056     function ary(func, n, guard) {
10057       n = guard ? undefined : n;
10058       n = (func && n == null) ? func.length : n;
10059       return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10060     }
10061
10062     /**
10063      * Creates a function that invokes `func`, with the `this` binding and arguments
10064      * of the created function, while it's called less than `n` times. Subsequent
10065      * calls to the created function return the result of the last `func` invocation.
10066      *
10067      * @static
10068      * @memberOf _
10069      * @since 3.0.0
10070      * @category Function
10071      * @param {number} n The number of calls at which `func` is no longer invoked.
10072      * @param {Function} func The function to restrict.
10073      * @returns {Function} Returns the new restricted function.
10074      * @example
10075      *
10076      * jQuery(element).on('click', _.before(5, addContactToList));
10077      * // => Allows adding up to 4 contacts to the list.
10078      */
10079     function before(n, func) {
10080       var result;
10081       if (typeof func != 'function') {
10082         throw new TypeError(FUNC_ERROR_TEXT);
10083       }
10084       n = toInteger(n);
10085       return function() {
10086         if (--n > 0) {
10087           result = func.apply(this, arguments);
10088         }
10089         if (n <= 1) {
10090           func = undefined;
10091         }
10092         return result;
10093       };
10094     }
10095
10096     /**
10097      * Creates a function that invokes `func` with the `this` binding of `thisArg`
10098      * and `partials` prepended to the arguments it receives.
10099      *
10100      * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10101      * may be used as a placeholder for partially applied arguments.
10102      *
10103      * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10104      * property of bound functions.
10105      *
10106      * @static
10107      * @memberOf _
10108      * @since 0.1.0
10109      * @category Function
10110      * @param {Function} func The function to bind.
10111      * @param {*} thisArg The `this` binding of `func`.
10112      * @param {...*} [partials] The arguments to be partially applied.
10113      * @returns {Function} Returns the new bound function.
10114      * @example
10115      *
10116      * function greet(greeting, punctuation) {
10117      *   return greeting + ' ' + this.user + punctuation;
10118      * }
10119      *
10120      * var object = { 'user': 'fred' };
10121      *
10122      * var bound = _.bind(greet, object, 'hi');
10123      * bound('!');
10124      * // => 'hi fred!'
10125      *
10126      * // Bound with placeholders.
10127      * var bound = _.bind(greet, object, _, '!');
10128      * bound('hi');
10129      * // => 'hi fred!'
10130      */
10131     var bind = baseRest(function(func, thisArg, partials) {
10132       var bitmask = WRAP_BIND_FLAG;
10133       if (partials.length) {
10134         var holders = replaceHolders(partials, getHolder(bind));
10135         bitmask |= WRAP_PARTIAL_FLAG;
10136       }
10137       return createWrap(func, bitmask, thisArg, partials, holders);
10138     });
10139
10140     /**
10141      * Creates a function that invokes the method at `object[key]` with `partials`
10142      * prepended to the arguments it receives.
10143      *
10144      * This method differs from `_.bind` by allowing bound functions to reference
10145      * methods that may be redefined or don't yet exist. See
10146      * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10147      * for more details.
10148      *
10149      * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10150      * builds, may be used as a placeholder for partially applied arguments.
10151      *
10152      * @static
10153      * @memberOf _
10154      * @since 0.10.0
10155      * @category Function
10156      * @param {Object} object The object to invoke the method on.
10157      * @param {string} key The key of the method.
10158      * @param {...*} [partials] The arguments to be partially applied.
10159      * @returns {Function} Returns the new bound function.
10160      * @example
10161      *
10162      * var object = {
10163      *   'user': 'fred',
10164      *   'greet': function(greeting, punctuation) {
10165      *     return greeting + ' ' + this.user + punctuation;
10166      *   }
10167      * };
10168      *
10169      * var bound = _.bindKey(object, 'greet', 'hi');
10170      * bound('!');
10171      * // => 'hi fred!'
10172      *
10173      * object.greet = function(greeting, punctuation) {
10174      *   return greeting + 'ya ' + this.user + punctuation;
10175      * };
10176      *
10177      * bound('!');
10178      * // => 'hiya fred!'
10179      *
10180      * // Bound with placeholders.
10181      * var bound = _.bindKey(object, 'greet', _, '!');
10182      * bound('hi');
10183      * // => 'hiya fred!'
10184      */
10185     var bindKey = baseRest(function(object, key, partials) {
10186       var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10187       if (partials.length) {
10188         var holders = replaceHolders(partials, getHolder(bindKey));
10189         bitmask |= WRAP_PARTIAL_FLAG;
10190       }
10191       return createWrap(key, bitmask, object, partials, holders);
10192     });
10193
10194     /**
10195      * Creates a function that accepts arguments of `func` and either invokes
10196      * `func` returning its result, if at least `arity` number of arguments have
10197      * been provided, or returns a function that accepts the remaining `func`
10198      * arguments, and so on. The arity of `func` may be specified if `func.length`
10199      * is not sufficient.
10200      *
10201      * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10202      * may be used as a placeholder for provided arguments.
10203      *
10204      * **Note:** This method doesn't set the "length" property of curried functions.
10205      *
10206      * @static
10207      * @memberOf _
10208      * @since 2.0.0
10209      * @category Function
10210      * @param {Function} func The function to curry.
10211      * @param {number} [arity=func.length] The arity of `func`.
10212      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10213      * @returns {Function} Returns the new curried function.
10214      * @example
10215      *
10216      * var abc = function(a, b, c) {
10217      *   return [a, b, c];
10218      * };
10219      *
10220      * var curried = _.curry(abc);
10221      *
10222      * curried(1)(2)(3);
10223      * // => [1, 2, 3]
10224      *
10225      * curried(1, 2)(3);
10226      * // => [1, 2, 3]
10227      *
10228      * curried(1, 2, 3);
10229      * // => [1, 2, 3]
10230      *
10231      * // Curried with placeholders.
10232      * curried(1)(_, 3)(2);
10233      * // => [1, 2, 3]
10234      */
10235     function curry(func, arity, guard) {
10236       arity = guard ? undefined : arity;
10237       var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10238       result.placeholder = curry.placeholder;
10239       return result;
10240     }
10241
10242     /**
10243      * This method is like `_.curry` except that arguments are applied to `func`
10244      * in the manner of `_.partialRight` instead of `_.partial`.
10245      *
10246      * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10247      * builds, may be used as a placeholder for provided arguments.
10248      *
10249      * **Note:** This method doesn't set the "length" property of curried functions.
10250      *
10251      * @static
10252      * @memberOf _
10253      * @since 3.0.0
10254      * @category Function
10255      * @param {Function} func The function to curry.
10256      * @param {number} [arity=func.length] The arity of `func`.
10257      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10258      * @returns {Function} Returns the new curried function.
10259      * @example
10260      *
10261      * var abc = function(a, b, c) {
10262      *   return [a, b, c];
10263      * };
10264      *
10265      * var curried = _.curryRight(abc);
10266      *
10267      * curried(3)(2)(1);
10268      * // => [1, 2, 3]
10269      *
10270      * curried(2, 3)(1);
10271      * // => [1, 2, 3]
10272      *
10273      * curried(1, 2, 3);
10274      * // => [1, 2, 3]
10275      *
10276      * // Curried with placeholders.
10277      * curried(3)(1, _)(2);
10278      * // => [1, 2, 3]
10279      */
10280     function curryRight(func, arity, guard) {
10281       arity = guard ? undefined : arity;
10282       var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10283       result.placeholder = curryRight.placeholder;
10284       return result;
10285     }
10286
10287     /**
10288      * Creates a debounced function that delays invoking `func` until after `wait`
10289      * milliseconds have elapsed since the last time the debounced function was
10290      * invoked. The debounced function comes with a `cancel` method to cancel
10291      * delayed `func` invocations and a `flush` method to immediately invoke them.
10292      * Provide `options` to indicate whether `func` should be invoked on the
10293      * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10294      * with the last arguments provided to the debounced function. Subsequent
10295      * calls to the debounced function return the result of the last `func`
10296      * invocation.
10297      *
10298      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10299      * invoked on the trailing edge of the timeout only if the debounced function
10300      * is invoked more than once during the `wait` timeout.
10301      *
10302      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10303      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10304      *
10305      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10306      * for details over the differences between `_.debounce` and `_.throttle`.
10307      *
10308      * @static
10309      * @memberOf _
10310      * @since 0.1.0
10311      * @category Function
10312      * @param {Function} func The function to debounce.
10313      * @param {number} [wait=0] The number of milliseconds to delay.
10314      * @param {Object} [options={}] The options object.
10315      * @param {boolean} [options.leading=false]
10316      *  Specify invoking on the leading edge of the timeout.
10317      * @param {number} [options.maxWait]
10318      *  The maximum time `func` is allowed to be delayed before it's invoked.
10319      * @param {boolean} [options.trailing=true]
10320      *  Specify invoking on the trailing edge of the timeout.
10321      * @returns {Function} Returns the new debounced function.
10322      * @example
10323      *
10324      * // Avoid costly calculations while the window size is in flux.
10325      * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10326      *
10327      * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10328      * jQuery(element).on('click', _.debounce(sendMail, 300, {
10329      *   'leading': true,
10330      *   'trailing': false
10331      * }));
10332      *
10333      * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10334      * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10335      * var source = new EventSource('/stream');
10336      * jQuery(source).on('message', debounced);
10337      *
10338      * // Cancel the trailing debounced invocation.
10339      * jQuery(window).on('popstate', debounced.cancel);
10340      */
10341     function debounce(func, wait, options) {
10342       var lastArgs,
10343           lastThis,
10344           maxWait,
10345           result,
10346           timerId,
10347           lastCallTime,
10348           lastInvokeTime = 0,
10349           leading = false,
10350           maxing = false,
10351           trailing = true;
10352
10353       if (typeof func != 'function') {
10354         throw new TypeError(FUNC_ERROR_TEXT);
10355       }
10356       wait = toNumber(wait) || 0;
10357       if (isObject(options)) {
10358         leading = !!options.leading;
10359         maxing = 'maxWait' in options;
10360         maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10361         trailing = 'trailing' in options ? !!options.trailing : trailing;
10362       }
10363
10364       function invokeFunc(time) {
10365         var args = lastArgs,
10366             thisArg = lastThis;
10367
10368         lastArgs = lastThis = undefined;
10369         lastInvokeTime = time;
10370         result = func.apply(thisArg, args);
10371         return result;
10372       }
10373
10374       function leadingEdge(time) {
10375         // Reset any `maxWait` timer.
10376         lastInvokeTime = time;
10377         // Start the timer for the trailing edge.
10378         timerId = setTimeout(timerExpired, wait);
10379         // Invoke the leading edge.
10380         return leading ? invokeFunc(time) : result;
10381       }
10382
10383       function remainingWait(time) {
10384         var timeSinceLastCall = time - lastCallTime,
10385             timeSinceLastInvoke = time - lastInvokeTime,
10386             result = wait - timeSinceLastCall;
10387
10388         return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10389       }
10390
10391       function shouldInvoke(time) {
10392         var timeSinceLastCall = time - lastCallTime,
10393             timeSinceLastInvoke = time - lastInvokeTime;
10394
10395         // Either this is the first call, activity has stopped and we're at the
10396         // trailing edge, the system time has gone backwards and we're treating
10397         // it as the trailing edge, or we've hit the `maxWait` limit.
10398         return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10399           (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10400       }
10401
10402       function timerExpired() {
10403         var time = now();
10404         if (shouldInvoke(time)) {
10405           return trailingEdge(time);
10406         }
10407         // Restart the timer.
10408         timerId = setTimeout(timerExpired, remainingWait(time));
10409       }
10410
10411       function trailingEdge(time) {
10412         timerId = undefined;
10413
10414         // Only invoke if we have `lastArgs` which means `func` has been
10415         // debounced at least once.
10416         if (trailing && lastArgs) {
10417           return invokeFunc(time);
10418         }
10419         lastArgs = lastThis = undefined;
10420         return result;
10421       }
10422
10423       function cancel() {
10424         if (timerId !== undefined) {
10425           clearTimeout(timerId);
10426         }
10427         lastInvokeTime = 0;
10428         lastArgs = lastCallTime = lastThis = timerId = undefined;
10429       }
10430
10431       function flush() {
10432         return timerId === undefined ? result : trailingEdge(now());
10433       }
10434
10435       function debounced() {
10436         var time = now(),
10437             isInvoking = shouldInvoke(time);
10438
10439         lastArgs = arguments;
10440         lastThis = this;
10441         lastCallTime = time;
10442
10443         if (isInvoking) {
10444           if (timerId === undefined) {
10445             return leadingEdge(lastCallTime);
10446           }
10447           if (maxing) {
10448             // Handle invocations in a tight loop.
10449             timerId = setTimeout(timerExpired, wait);
10450             return invokeFunc(lastCallTime);
10451           }
10452         }
10453         if (timerId === undefined) {
10454           timerId = setTimeout(timerExpired, wait);
10455         }
10456         return result;
10457       }
10458       debounced.cancel = cancel;
10459       debounced.flush = flush;
10460       return debounced;
10461     }
10462
10463     /**
10464      * Defers invoking the `func` until the current call stack has cleared. Any
10465      * additional arguments are provided to `func` when it's invoked.
10466      *
10467      * @static
10468      * @memberOf _
10469      * @since 0.1.0
10470      * @category Function
10471      * @param {Function} func The function to defer.
10472      * @param {...*} [args] The arguments to invoke `func` with.
10473      * @returns {number} Returns the timer id.
10474      * @example
10475      *
10476      * _.defer(function(text) {
10477      *   console.log(text);
10478      * }, 'deferred');
10479      * // => Logs 'deferred' after one millisecond.
10480      */
10481     var defer = baseRest(function(func, args) {
10482       return baseDelay(func, 1, args);
10483     });
10484
10485     /**
10486      * Invokes `func` after `wait` milliseconds. Any additional arguments are
10487      * provided to `func` when it's invoked.
10488      *
10489      * @static
10490      * @memberOf _
10491      * @since 0.1.0
10492      * @category Function
10493      * @param {Function} func The function to delay.
10494      * @param {number} wait The number of milliseconds to delay invocation.
10495      * @param {...*} [args] The arguments to invoke `func` with.
10496      * @returns {number} Returns the timer id.
10497      * @example
10498      *
10499      * _.delay(function(text) {
10500      *   console.log(text);
10501      * }, 1000, 'later');
10502      * // => Logs 'later' after one second.
10503      */
10504     var delay = baseRest(function(func, wait, args) {
10505       return baseDelay(func, toNumber(wait) || 0, args);
10506     });
10507
10508     /**
10509      * Creates a function that invokes `func` with arguments reversed.
10510      *
10511      * @static
10512      * @memberOf _
10513      * @since 4.0.0
10514      * @category Function
10515      * @param {Function} func The function to flip arguments for.
10516      * @returns {Function} Returns the new flipped function.
10517      * @example
10518      *
10519      * var flipped = _.flip(function() {
10520      *   return _.toArray(arguments);
10521      * });
10522      *
10523      * flipped('a', 'b', 'c', 'd');
10524      * // => ['d', 'c', 'b', 'a']
10525      */
10526     function flip(func) {
10527       return createWrap(func, WRAP_FLIP_FLAG);
10528     }
10529
10530     /**
10531      * Creates a function that memoizes the result of `func`. If `resolver` is
10532      * provided, it determines the cache key for storing the result based on the
10533      * arguments provided to the memoized function. By default, the first argument
10534      * provided to the memoized function is used as the map cache key. The `func`
10535      * is invoked with the `this` binding of the memoized function.
10536      *
10537      * **Note:** The cache is exposed as the `cache` property on the memoized
10538      * function. Its creation may be customized by replacing the `_.memoize.Cache`
10539      * constructor with one whose instances implement the
10540      * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10541      * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10542      *
10543      * @static
10544      * @memberOf _
10545      * @since 0.1.0
10546      * @category Function
10547      * @param {Function} func The function to have its output memoized.
10548      * @param {Function} [resolver] The function to resolve the cache key.
10549      * @returns {Function} Returns the new memoized function.
10550      * @example
10551      *
10552      * var object = { 'a': 1, 'b': 2 };
10553      * var other = { 'c': 3, 'd': 4 };
10554      *
10555      * var values = _.memoize(_.values);
10556      * values(object);
10557      * // => [1, 2]
10558      *
10559      * values(other);
10560      * // => [3, 4]
10561      *
10562      * object.a = 2;
10563      * values(object);
10564      * // => [1, 2]
10565      *
10566      * // Modify the result cache.
10567      * values.cache.set(object, ['a', 'b']);
10568      * values(object);
10569      * // => ['a', 'b']
10570      *
10571      * // Replace `_.memoize.Cache`.
10572      * _.memoize.Cache = WeakMap;
10573      */
10574     function memoize(func, resolver) {
10575       if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10576         throw new TypeError(FUNC_ERROR_TEXT);
10577       }
10578       var memoized = function() {
10579         var args = arguments,
10580             key = resolver ? resolver.apply(this, args) : args[0],
10581             cache = memoized.cache;
10582
10583         if (cache.has(key)) {
10584           return cache.get(key);
10585         }
10586         var result = func.apply(this, args);
10587         memoized.cache = cache.set(key, result) || cache;
10588         return result;
10589       };
10590       memoized.cache = new (memoize.Cache || MapCache);
10591       return memoized;
10592     }
10593
10594     // Expose `MapCache`.
10595     memoize.Cache = MapCache;
10596
10597     /**
10598      * Creates a function that negates the result of the predicate `func`. The
10599      * `func` predicate is invoked with the `this` binding and arguments of the
10600      * created function.
10601      *
10602      * @static
10603      * @memberOf _
10604      * @since 3.0.0
10605      * @category Function
10606      * @param {Function} predicate The predicate to negate.
10607      * @returns {Function} Returns the new negated function.
10608      * @example
10609      *
10610      * function isEven(n) {
10611      *   return n % 2 == 0;
10612      * }
10613      *
10614      * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10615      * // => [1, 3, 5]
10616      */
10617     function negate(predicate) {
10618       if (typeof predicate != 'function') {
10619         throw new TypeError(FUNC_ERROR_TEXT);
10620       }
10621       return function() {
10622         var args = arguments;
10623         switch (args.length) {
10624           case 0: return !predicate.call(this);
10625           case 1: return !predicate.call(this, args[0]);
10626           case 2: return !predicate.call(this, args[0], args[1]);
10627           case 3: return !predicate.call(this, args[0], args[1], args[2]);
10628         }
10629         return !predicate.apply(this, args);
10630       };
10631     }
10632
10633     /**
10634      * Creates a function that is restricted to invoking `func` once. Repeat calls
10635      * to the function return the value of the first invocation. The `func` is
10636      * invoked with the `this` binding and arguments of the created function.
10637      *
10638      * @static
10639      * @memberOf _
10640      * @since 0.1.0
10641      * @category Function
10642      * @param {Function} func The function to restrict.
10643      * @returns {Function} Returns the new restricted function.
10644      * @example
10645      *
10646      * var initialize = _.once(createApplication);
10647      * initialize();
10648      * initialize();
10649      * // => `createApplication` is invoked once
10650      */
10651     function once(func) {
10652       return before(2, func);
10653     }
10654
10655     /**
10656      * Creates a function that invokes `func` with its arguments transformed.
10657      *
10658      * @static
10659      * @since 4.0.0
10660      * @memberOf _
10661      * @category Function
10662      * @param {Function} func The function to wrap.
10663      * @param {...(Function|Function[])} [transforms=[_.identity]]
10664      *  The argument transforms.
10665      * @returns {Function} Returns the new function.
10666      * @example
10667      *
10668      * function doubled(n) {
10669      *   return n * 2;
10670      * }
10671      *
10672      * function square(n) {
10673      *   return n * n;
10674      * }
10675      *
10676      * var func = _.overArgs(function(x, y) {
10677      *   return [x, y];
10678      * }, [square, doubled]);
10679      *
10680      * func(9, 3);
10681      * // => [81, 6]
10682      *
10683      * func(10, 5);
10684      * // => [100, 10]
10685      */
10686     var overArgs = castRest(function(func, transforms) {
10687       transforms = (transforms.length == 1 && isArray(transforms[0]))
10688         ? arrayMap(transforms[0], baseUnary(getIteratee()))
10689         : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10690
10691       var funcsLength = transforms.length;
10692       return baseRest(function(args) {
10693         var index = -1,
10694             length = nativeMin(args.length, funcsLength);
10695
10696         while (++index < length) {
10697           args[index] = transforms[index].call(this, args[index]);
10698         }
10699         return apply(func, this, args);
10700       });
10701     });
10702
10703     /**
10704      * Creates a function that invokes `func` with `partials` prepended to the
10705      * arguments it receives. This method is like `_.bind` except it does **not**
10706      * alter the `this` binding.
10707      *
10708      * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10709      * builds, may be used as a placeholder for partially applied arguments.
10710      *
10711      * **Note:** This method doesn't set the "length" property of partially
10712      * applied functions.
10713      *
10714      * @static
10715      * @memberOf _
10716      * @since 0.2.0
10717      * @category Function
10718      * @param {Function} func The function to partially apply arguments to.
10719      * @param {...*} [partials] The arguments to be partially applied.
10720      * @returns {Function} Returns the new partially applied function.
10721      * @example
10722      *
10723      * function greet(greeting, name) {
10724      *   return greeting + ' ' + name;
10725      * }
10726      *
10727      * var sayHelloTo = _.partial(greet, 'hello');
10728      * sayHelloTo('fred');
10729      * // => 'hello fred'
10730      *
10731      * // Partially applied with placeholders.
10732      * var greetFred = _.partial(greet, _, 'fred');
10733      * greetFred('hi');
10734      * // => 'hi fred'
10735      */
10736     var partial = baseRest(function(func, partials) {
10737       var holders = replaceHolders(partials, getHolder(partial));
10738       return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10739     });
10740
10741     /**
10742      * This method is like `_.partial` except that partially applied arguments
10743      * are appended to the arguments it receives.
10744      *
10745      * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10746      * builds, may be used as a placeholder for partially applied arguments.
10747      *
10748      * **Note:** This method doesn't set the "length" property of partially
10749      * applied functions.
10750      *
10751      * @static
10752      * @memberOf _
10753      * @since 1.0.0
10754      * @category Function
10755      * @param {Function} func The function to partially apply arguments to.
10756      * @param {...*} [partials] The arguments to be partially applied.
10757      * @returns {Function} Returns the new partially applied function.
10758      * @example
10759      *
10760      * function greet(greeting, name) {
10761      *   return greeting + ' ' + name;
10762      * }
10763      *
10764      * var greetFred = _.partialRight(greet, 'fred');
10765      * greetFred('hi');
10766      * // => 'hi fred'
10767      *
10768      * // Partially applied with placeholders.
10769      * var sayHelloTo = _.partialRight(greet, 'hello', _);
10770      * sayHelloTo('fred');
10771      * // => 'hello fred'
10772      */
10773     var partialRight = baseRest(function(func, partials) {
10774       var holders = replaceHolders(partials, getHolder(partialRight));
10775       return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10776     });
10777
10778     /**
10779      * Creates a function that invokes `func` with arguments arranged according
10780      * to the specified `indexes` where the argument value at the first index is
10781      * provided as the first argument, the argument value at the second index is
10782      * provided as the second argument, and so on.
10783      *
10784      * @static
10785      * @memberOf _
10786      * @since 3.0.0
10787      * @category Function
10788      * @param {Function} func The function to rearrange arguments for.
10789      * @param {...(number|number[])} indexes The arranged argument indexes.
10790      * @returns {Function} Returns the new function.
10791      * @example
10792      *
10793      * var rearged = _.rearg(function(a, b, c) {
10794      *   return [a, b, c];
10795      * }, [2, 0, 1]);
10796      *
10797      * rearged('b', 'c', 'a')
10798      * // => ['a', 'b', 'c']
10799      */
10800     var rearg = flatRest(function(func, indexes) {
10801       return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10802     });
10803
10804     /**
10805      * Creates a function that invokes `func` with the `this` binding of the
10806      * created function and arguments from `start` and beyond provided as
10807      * an array.
10808      *
10809      * **Note:** This method is based on the
10810      * [rest parameter](https://mdn.io/rest_parameters).
10811      *
10812      * @static
10813      * @memberOf _
10814      * @since 4.0.0
10815      * @category Function
10816      * @param {Function} func The function to apply a rest parameter to.
10817      * @param {number} [start=func.length-1] The start position of the rest parameter.
10818      * @returns {Function} Returns the new function.
10819      * @example
10820      *
10821      * var say = _.rest(function(what, names) {
10822      *   return what + ' ' + _.initial(names).join(', ') +
10823      *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10824      * });
10825      *
10826      * say('hello', 'fred', 'barney', 'pebbles');
10827      * // => 'hello fred, barney, & pebbles'
10828      */
10829     function rest(func, start) {
10830       if (typeof func != 'function') {
10831         throw new TypeError(FUNC_ERROR_TEXT);
10832       }
10833       start = start === undefined ? start : toInteger(start);
10834       return baseRest(func, start);
10835     }
10836
10837     /**
10838      * Creates a function that invokes `func` with the `this` binding of the
10839      * create function and an array of arguments much like
10840      * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10841      *
10842      * **Note:** This method is based on the
10843      * [spread operator](https://mdn.io/spread_operator).
10844      *
10845      * @static
10846      * @memberOf _
10847      * @since 3.2.0
10848      * @category Function
10849      * @param {Function} func The function to spread arguments over.
10850      * @param {number} [start=0] The start position of the spread.
10851      * @returns {Function} Returns the new function.
10852      * @example
10853      *
10854      * var say = _.spread(function(who, what) {
10855      *   return who + ' says ' + what;
10856      * });
10857      *
10858      * say(['fred', 'hello']);
10859      * // => 'fred says hello'
10860      *
10861      * var numbers = Promise.all([
10862      *   Promise.resolve(40),
10863      *   Promise.resolve(36)
10864      * ]);
10865      *
10866      * numbers.then(_.spread(function(x, y) {
10867      *   return x + y;
10868      * }));
10869      * // => a Promise of 76
10870      */
10871     function spread(func, start) {
10872       if (typeof func != 'function') {
10873         throw new TypeError(FUNC_ERROR_TEXT);
10874       }
10875       start = start == null ? 0 : nativeMax(toInteger(start), 0);
10876       return baseRest(function(args) {
10877         var array = args[start],
10878             otherArgs = castSlice(args, 0, start);
10879
10880         if (array) {
10881           arrayPush(otherArgs, array);
10882         }
10883         return apply(func, this, otherArgs);
10884       });
10885     }
10886
10887     /**
10888      * Creates a throttled function that only invokes `func` at most once per
10889      * every `wait` milliseconds. The throttled function comes with a `cancel`
10890      * method to cancel delayed `func` invocations and a `flush` method to
10891      * immediately invoke them. Provide `options` to indicate whether `func`
10892      * should be invoked on the leading and/or trailing edge of the `wait`
10893      * timeout. The `func` is invoked with the last arguments provided to the
10894      * throttled function. Subsequent calls to the throttled function return the
10895      * result of the last `func` invocation.
10896      *
10897      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10898      * invoked on the trailing edge of the timeout only if the throttled function
10899      * is invoked more than once during the `wait` timeout.
10900      *
10901      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10902      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10903      *
10904      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10905      * for details over the differences between `_.throttle` and `_.debounce`.
10906      *
10907      * @static
10908      * @memberOf _
10909      * @since 0.1.0
10910      * @category Function
10911      * @param {Function} func The function to throttle.
10912      * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10913      * @param {Object} [options={}] The options object.
10914      * @param {boolean} [options.leading=true]
10915      *  Specify invoking on the leading edge of the timeout.
10916      * @param {boolean} [options.trailing=true]
10917      *  Specify invoking on the trailing edge of the timeout.
10918      * @returns {Function} Returns the new throttled function.
10919      * @example
10920      *
10921      * // Avoid excessively updating the position while scrolling.
10922      * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10923      *
10924      * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10925      * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10926      * jQuery(element).on('click', throttled);
10927      *
10928      * // Cancel the trailing throttled invocation.
10929      * jQuery(window).on('popstate', throttled.cancel);
10930      */
10931     function throttle(func, wait, options) {
10932       var leading = true,
10933           trailing = true;
10934
10935       if (typeof func != 'function') {
10936         throw new TypeError(FUNC_ERROR_TEXT);
10937       }
10938       if (isObject(options)) {
10939         leading = 'leading' in options ? !!options.leading : leading;
10940         trailing = 'trailing' in options ? !!options.trailing : trailing;
10941       }
10942       return debounce(func, wait, {
10943         'leading': leading,
10944         'maxWait': wait,
10945         'trailing': trailing
10946       });
10947     }
10948
10949     /**
10950      * Creates a function that accepts up to one argument, ignoring any
10951      * additional arguments.
10952      *
10953      * @static
10954      * @memberOf _
10955      * @since 4.0.0
10956      * @category Function
10957      * @param {Function} func The function to cap arguments for.
10958      * @returns {Function} Returns the new capped function.
10959      * @example
10960      *
10961      * _.map(['6', '8', '10'], _.unary(parseInt));
10962      * // => [6, 8, 10]
10963      */
10964     function unary(func) {
10965       return ary(func, 1);
10966     }
10967
10968     /**
10969      * Creates a function that provides `value` to `wrapper` as its first
10970      * argument. Any additional arguments provided to the function are appended
10971      * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10972      * binding of the created function.
10973      *
10974      * @static
10975      * @memberOf _
10976      * @since 0.1.0
10977      * @category Function
10978      * @param {*} value The value to wrap.
10979      * @param {Function} [wrapper=identity] The wrapper function.
10980      * @returns {Function} Returns the new function.
10981      * @example
10982      *
10983      * var p = _.wrap(_.escape, function(func, text) {
10984      *   return '<p>' + func(text) + '</p>';
10985      * });
10986      *
10987      * p('fred, barney, & pebbles');
10988      * // => '<p>fred, barney, &amp; pebbles</p>'
10989      */
10990     function wrap(value, wrapper) {
10991       return partial(castFunction(wrapper), value);
10992     }
10993
10994     /*------------------------------------------------------------------------*/
10995
10996     /**
10997      * Casts `value` as an array if it's not one.
10998      *
10999      * @static
11000      * @memberOf _
11001      * @since 4.4.0
11002      * @category Lang
11003      * @param {*} value The value to inspect.
11004      * @returns {Array} Returns the cast array.
11005      * @example
11006      *
11007      * _.castArray(1);
11008      * // => [1]
11009      *
11010      * _.castArray({ 'a': 1 });
11011      * // => [{ 'a': 1 }]
11012      *
11013      * _.castArray('abc');
11014      * // => ['abc']
11015      *
11016      * _.castArray(null);
11017      * // => [null]
11018      *
11019      * _.castArray(undefined);
11020      * // => [undefined]
11021      *
11022      * _.castArray();
11023      * // => []
11024      *
11025      * var array = [1, 2, 3];
11026      * console.log(_.castArray(array) === array);
11027      * // => true
11028      */
11029     function castArray() {
11030       if (!arguments.length) {
11031         return [];
11032       }
11033       var value = arguments[0];
11034       return isArray(value) ? value : [value];
11035     }
11036
11037     /**
11038      * Creates a shallow clone of `value`.
11039      *
11040      * **Note:** This method is loosely based on the
11041      * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11042      * and supports cloning arrays, array buffers, booleans, date objects, maps,
11043      * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11044      * arrays. The own enumerable properties of `arguments` objects are cloned
11045      * as plain objects. An empty object is returned for uncloneable values such
11046      * as error objects, functions, DOM nodes, and WeakMaps.
11047      *
11048      * @static
11049      * @memberOf _
11050      * @since 0.1.0
11051      * @category Lang
11052      * @param {*} value The value to clone.
11053      * @returns {*} Returns the cloned value.
11054      * @see _.cloneDeep
11055      * @example
11056      *
11057      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11058      *
11059      * var shallow = _.clone(objects);
11060      * console.log(shallow[0] === objects[0]);
11061      * // => true
11062      */
11063     function clone(value) {
11064       return baseClone(value, CLONE_SYMBOLS_FLAG);
11065     }
11066
11067     /**
11068      * This method is like `_.clone` except that it accepts `customizer` which
11069      * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11070      * cloning is handled by the method instead. The `customizer` is invoked with
11071      * up to four arguments; (value [, index|key, object, stack]).
11072      *
11073      * @static
11074      * @memberOf _
11075      * @since 4.0.0
11076      * @category Lang
11077      * @param {*} value The value to clone.
11078      * @param {Function} [customizer] The function to customize cloning.
11079      * @returns {*} Returns the cloned value.
11080      * @see _.cloneDeepWith
11081      * @example
11082      *
11083      * function customizer(value) {
11084      *   if (_.isElement(value)) {
11085      *     return value.cloneNode(false);
11086      *   }
11087      * }
11088      *
11089      * var el = _.cloneWith(document.body, customizer);
11090      *
11091      * console.log(el === document.body);
11092      * // => false
11093      * console.log(el.nodeName);
11094      * // => 'BODY'
11095      * console.log(el.childNodes.length);
11096      * // => 0
11097      */
11098     function cloneWith(value, customizer) {
11099       customizer = typeof customizer == 'function' ? customizer : undefined;
11100       return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11101     }
11102
11103     /**
11104      * This method is like `_.clone` except that it recursively clones `value`.
11105      *
11106      * @static
11107      * @memberOf _
11108      * @since 1.0.0
11109      * @category Lang
11110      * @param {*} value The value to recursively clone.
11111      * @returns {*} Returns the deep cloned value.
11112      * @see _.clone
11113      * @example
11114      *
11115      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11116      *
11117      * var deep = _.cloneDeep(objects);
11118      * console.log(deep[0] === objects[0]);
11119      * // => false
11120      */
11121     function cloneDeep(value) {
11122       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11123     }
11124
11125     /**
11126      * This method is like `_.cloneWith` except that it recursively clones `value`.
11127      *
11128      * @static
11129      * @memberOf _
11130      * @since 4.0.0
11131      * @category Lang
11132      * @param {*} value The value to recursively clone.
11133      * @param {Function} [customizer] The function to customize cloning.
11134      * @returns {*} Returns the deep cloned value.
11135      * @see _.cloneWith
11136      * @example
11137      *
11138      * function customizer(value) {
11139      *   if (_.isElement(value)) {
11140      *     return value.cloneNode(true);
11141      *   }
11142      * }
11143      *
11144      * var el = _.cloneDeepWith(document.body, customizer);
11145      *
11146      * console.log(el === document.body);
11147      * // => false
11148      * console.log(el.nodeName);
11149      * // => 'BODY'
11150      * console.log(el.childNodes.length);
11151      * // => 20
11152      */
11153     function cloneDeepWith(value, customizer) {
11154       customizer = typeof customizer == 'function' ? customizer : undefined;
11155       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11156     }
11157
11158     /**
11159      * Checks if `object` conforms to `source` by invoking the predicate
11160      * properties of `source` with the corresponding property values of `object`.
11161      *
11162      * **Note:** This method is equivalent to `_.conforms` when `source` is
11163      * partially applied.
11164      *
11165      * @static
11166      * @memberOf _
11167      * @since 4.14.0
11168      * @category Lang
11169      * @param {Object} object The object to inspect.
11170      * @param {Object} source The object of property predicates to conform to.
11171      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11172      * @example
11173      *
11174      * var object = { 'a': 1, 'b': 2 };
11175      *
11176      * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11177      * // => true
11178      *
11179      * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11180      * // => false
11181      */
11182     function conformsTo(object, source) {
11183       return source == null || baseConformsTo(object, source, keys(source));
11184     }
11185
11186     /**
11187      * Performs a
11188      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11189      * comparison between two values to determine if they are equivalent.
11190      *
11191      * @static
11192      * @memberOf _
11193      * @since 4.0.0
11194      * @category Lang
11195      * @param {*} value The value to compare.
11196      * @param {*} other The other value to compare.
11197      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11198      * @example
11199      *
11200      * var object = { 'a': 1 };
11201      * var other = { 'a': 1 };
11202      *
11203      * _.eq(object, object);
11204      * // => true
11205      *
11206      * _.eq(object, other);
11207      * // => false
11208      *
11209      * _.eq('a', 'a');
11210      * // => true
11211      *
11212      * _.eq('a', Object('a'));
11213      * // => false
11214      *
11215      * _.eq(NaN, NaN);
11216      * // => true
11217      */
11218     function eq(value, other) {
11219       return value === other || (value !== value && other !== other);
11220     }
11221
11222     /**
11223      * Checks if `value` is greater than `other`.
11224      *
11225      * @static
11226      * @memberOf _
11227      * @since 3.9.0
11228      * @category Lang
11229      * @param {*} value The value to compare.
11230      * @param {*} other The other value to compare.
11231      * @returns {boolean} Returns `true` if `value` is greater than `other`,
11232      *  else `false`.
11233      * @see _.lt
11234      * @example
11235      *
11236      * _.gt(3, 1);
11237      * // => true
11238      *
11239      * _.gt(3, 3);
11240      * // => false
11241      *
11242      * _.gt(1, 3);
11243      * // => false
11244      */
11245     var gt = createRelationalOperation(baseGt);
11246
11247     /**
11248      * Checks if `value` is greater than or equal to `other`.
11249      *
11250      * @static
11251      * @memberOf _
11252      * @since 3.9.0
11253      * @category Lang
11254      * @param {*} value The value to compare.
11255      * @param {*} other The other value to compare.
11256      * @returns {boolean} Returns `true` if `value` is greater than or equal to
11257      *  `other`, else `false`.
11258      * @see _.lte
11259      * @example
11260      *
11261      * _.gte(3, 1);
11262      * // => true
11263      *
11264      * _.gte(3, 3);
11265      * // => true
11266      *
11267      * _.gte(1, 3);
11268      * // => false
11269      */
11270     var gte = createRelationalOperation(function(value, other) {
11271       return value >= other;
11272     });
11273
11274     /**
11275      * Checks if `value` is likely an `arguments` object.
11276      *
11277      * @static
11278      * @memberOf _
11279      * @since 0.1.0
11280      * @category Lang
11281      * @param {*} value The value to check.
11282      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11283      *  else `false`.
11284      * @example
11285      *
11286      * _.isArguments(function() { return arguments; }());
11287      * // => true
11288      *
11289      * _.isArguments([1, 2, 3]);
11290      * // => false
11291      */
11292     var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11293       return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11294         !propertyIsEnumerable.call(value, 'callee');
11295     };
11296
11297     /**
11298      * Checks if `value` is classified as an `Array` object.
11299      *
11300      * @static
11301      * @memberOf _
11302      * @since 0.1.0
11303      * @category Lang
11304      * @param {*} value The value to check.
11305      * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11306      * @example
11307      *
11308      * _.isArray([1, 2, 3]);
11309      * // => true
11310      *
11311      * _.isArray(document.body.children);
11312      * // => false
11313      *
11314      * _.isArray('abc');
11315      * // => false
11316      *
11317      * _.isArray(_.noop);
11318      * // => false
11319      */
11320     var isArray = Array.isArray;
11321
11322     /**
11323      * Checks if `value` is classified as an `ArrayBuffer` object.
11324      *
11325      * @static
11326      * @memberOf _
11327      * @since 4.3.0
11328      * @category Lang
11329      * @param {*} value The value to check.
11330      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11331      * @example
11332      *
11333      * _.isArrayBuffer(new ArrayBuffer(2));
11334      * // => true
11335      *
11336      * _.isArrayBuffer(new Array(2));
11337      * // => false
11338      */
11339     var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11340
11341     /**
11342      * Checks if `value` is array-like. A value is considered array-like if it's
11343      * not a function and has a `value.length` that's an integer greater than or
11344      * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11345      *
11346      * @static
11347      * @memberOf _
11348      * @since 4.0.0
11349      * @category Lang
11350      * @param {*} value The value to check.
11351      * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11352      * @example
11353      *
11354      * _.isArrayLike([1, 2, 3]);
11355      * // => true
11356      *
11357      * _.isArrayLike(document.body.children);
11358      * // => true
11359      *
11360      * _.isArrayLike('abc');
11361      * // => true
11362      *
11363      * _.isArrayLike(_.noop);
11364      * // => false
11365      */
11366     function isArrayLike(value) {
11367       return value != null && isLength(value.length) && !isFunction(value);
11368     }
11369
11370     /**
11371      * This method is like `_.isArrayLike` except that it also checks if `value`
11372      * is an object.
11373      *
11374      * @static
11375      * @memberOf _
11376      * @since 4.0.0
11377      * @category Lang
11378      * @param {*} value The value to check.
11379      * @returns {boolean} Returns `true` if `value` is an array-like object,
11380      *  else `false`.
11381      * @example
11382      *
11383      * _.isArrayLikeObject([1, 2, 3]);
11384      * // => true
11385      *
11386      * _.isArrayLikeObject(document.body.children);
11387      * // => true
11388      *
11389      * _.isArrayLikeObject('abc');
11390      * // => false
11391      *
11392      * _.isArrayLikeObject(_.noop);
11393      * // => false
11394      */
11395     function isArrayLikeObject(value) {
11396       return isObjectLike(value) && isArrayLike(value);
11397     }
11398
11399     /**
11400      * Checks if `value` is classified as a boolean primitive or object.
11401      *
11402      * @static
11403      * @memberOf _
11404      * @since 0.1.0
11405      * @category Lang
11406      * @param {*} value The value to check.
11407      * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11408      * @example
11409      *
11410      * _.isBoolean(false);
11411      * // => true
11412      *
11413      * _.isBoolean(null);
11414      * // => false
11415      */
11416     function isBoolean(value) {
11417       return value === true || value === false ||
11418         (isObjectLike(value) && baseGetTag(value) == boolTag);
11419     }
11420
11421     /**
11422      * Checks if `value` is a buffer.
11423      *
11424      * @static
11425      * @memberOf _
11426      * @since 4.3.0
11427      * @category Lang
11428      * @param {*} value The value to check.
11429      * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11430      * @example
11431      *
11432      * _.isBuffer(new Buffer(2));
11433      * // => true
11434      *
11435      * _.isBuffer(new Uint8Array(2));
11436      * // => false
11437      */
11438     var isBuffer = nativeIsBuffer || stubFalse;
11439
11440     /**
11441      * Checks if `value` is classified as a `Date` object.
11442      *
11443      * @static
11444      * @memberOf _
11445      * @since 0.1.0
11446      * @category Lang
11447      * @param {*} value The value to check.
11448      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11449      * @example
11450      *
11451      * _.isDate(new Date);
11452      * // => true
11453      *
11454      * _.isDate('Mon April 23 2012');
11455      * // => false
11456      */
11457     var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11458
11459     /**
11460      * Checks if `value` is likely a DOM element.
11461      *
11462      * @static
11463      * @memberOf _
11464      * @since 0.1.0
11465      * @category Lang
11466      * @param {*} value The value to check.
11467      * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11468      * @example
11469      *
11470      * _.isElement(document.body);
11471      * // => true
11472      *
11473      * _.isElement('<body>');
11474      * // => false
11475      */
11476     function isElement(value) {
11477       return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11478     }
11479
11480     /**
11481      * Checks if `value` is an empty object, collection, map, or set.
11482      *
11483      * Objects are considered empty if they have no own enumerable string keyed
11484      * properties.
11485      *
11486      * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11487      * jQuery-like collections are considered empty if they have a `length` of `0`.
11488      * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11489      *
11490      * @static
11491      * @memberOf _
11492      * @since 0.1.0
11493      * @category Lang
11494      * @param {*} value The value to check.
11495      * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11496      * @example
11497      *
11498      * _.isEmpty(null);
11499      * // => true
11500      *
11501      * _.isEmpty(true);
11502      * // => true
11503      *
11504      * _.isEmpty(1);
11505      * // => true
11506      *
11507      * _.isEmpty([1, 2, 3]);
11508      * // => false
11509      *
11510      * _.isEmpty({ 'a': 1 });
11511      * // => false
11512      */
11513     function isEmpty(value) {
11514       if (value == null) {
11515         return true;
11516       }
11517       if (isArrayLike(value) &&
11518           (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11519             isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11520         return !value.length;
11521       }
11522       var tag = getTag(value);
11523       if (tag == mapTag || tag == setTag) {
11524         return !value.size;
11525       }
11526       if (isPrototype(value)) {
11527         return !baseKeys(value).length;
11528       }
11529       for (var key in value) {
11530         if (hasOwnProperty.call(value, key)) {
11531           return false;
11532         }
11533       }
11534       return true;
11535     }
11536
11537     /**
11538      * Performs a deep comparison between two values to determine if they are
11539      * equivalent.
11540      *
11541      * **Note:** This method supports comparing arrays, array buffers, booleans,
11542      * date objects, error objects, maps, numbers, `Object` objects, regexes,
11543      * sets, strings, symbols, and typed arrays. `Object` objects are compared
11544      * by their own, not inherited, enumerable properties. Functions and DOM
11545      * nodes are compared by strict equality, i.e. `===`.
11546      *
11547      * @static
11548      * @memberOf _
11549      * @since 0.1.0
11550      * @category Lang
11551      * @param {*} value The value to compare.
11552      * @param {*} other The other value to compare.
11553      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11554      * @example
11555      *
11556      * var object = { 'a': 1 };
11557      * var other = { 'a': 1 };
11558      *
11559      * _.isEqual(object, other);
11560      * // => true
11561      *
11562      * object === other;
11563      * // => false
11564      */
11565     function isEqual(value, other) {
11566       return baseIsEqual(value, other);
11567     }
11568
11569     /**
11570      * This method is like `_.isEqual` except that it accepts `customizer` which
11571      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11572      * are handled by the method instead. The `customizer` is invoked with up to
11573      * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11574      *
11575      * @static
11576      * @memberOf _
11577      * @since 4.0.0
11578      * @category Lang
11579      * @param {*} value The value to compare.
11580      * @param {*} other The other value to compare.
11581      * @param {Function} [customizer] The function to customize comparisons.
11582      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11583      * @example
11584      *
11585      * function isGreeting(value) {
11586      *   return /^h(?:i|ello)$/.test(value);
11587      * }
11588      *
11589      * function customizer(objValue, othValue) {
11590      *   if (isGreeting(objValue) && isGreeting(othValue)) {
11591      *     return true;
11592      *   }
11593      * }
11594      *
11595      * var array = ['hello', 'goodbye'];
11596      * var other = ['hi', 'goodbye'];
11597      *
11598      * _.isEqualWith(array, other, customizer);
11599      * // => true
11600      */
11601     function isEqualWith(value, other, customizer) {
11602       customizer = typeof customizer == 'function' ? customizer : undefined;
11603       var result = customizer ? customizer(value, other) : undefined;
11604       return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11605     }
11606
11607     /**
11608      * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11609      * `SyntaxError`, `TypeError`, or `URIError` object.
11610      *
11611      * @static
11612      * @memberOf _
11613      * @since 3.0.0
11614      * @category Lang
11615      * @param {*} value The value to check.
11616      * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11617      * @example
11618      *
11619      * _.isError(new Error);
11620      * // => true
11621      *
11622      * _.isError(Error);
11623      * // => false
11624      */
11625     function isError(value) {
11626       if (!isObjectLike(value)) {
11627         return false;
11628       }
11629       var tag = baseGetTag(value);
11630       return tag == errorTag || tag == domExcTag ||
11631         (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11632     }
11633
11634     /**
11635      * Checks if `value` is a finite primitive number.
11636      *
11637      * **Note:** This method is based on
11638      * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11639      *
11640      * @static
11641      * @memberOf _
11642      * @since 0.1.0
11643      * @category Lang
11644      * @param {*} value The value to check.
11645      * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11646      * @example
11647      *
11648      * _.isFinite(3);
11649      * // => true
11650      *
11651      * _.isFinite(Number.MIN_VALUE);
11652      * // => true
11653      *
11654      * _.isFinite(Infinity);
11655      * // => false
11656      *
11657      * _.isFinite('3');
11658      * // => false
11659      */
11660     function isFinite(value) {
11661       return typeof value == 'number' && nativeIsFinite(value);
11662     }
11663
11664     /**
11665      * Checks if `value` is classified as a `Function` object.
11666      *
11667      * @static
11668      * @memberOf _
11669      * @since 0.1.0
11670      * @category Lang
11671      * @param {*} value The value to check.
11672      * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11673      * @example
11674      *
11675      * _.isFunction(_);
11676      * // => true
11677      *
11678      * _.isFunction(/abc/);
11679      * // => false
11680      */
11681     function isFunction(value) {
11682       if (!isObject(value)) {
11683         return false;
11684       }
11685       // The use of `Object#toString` avoids issues with the `typeof` operator
11686       // in Safari 9 which returns 'object' for typed arrays and other constructors.
11687       var tag = baseGetTag(value);
11688       return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11689     }
11690
11691     /**
11692      * Checks if `value` is an integer.
11693      *
11694      * **Note:** This method is based on
11695      * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11696      *
11697      * @static
11698      * @memberOf _
11699      * @since 4.0.0
11700      * @category Lang
11701      * @param {*} value The value to check.
11702      * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11703      * @example
11704      *
11705      * _.isInteger(3);
11706      * // => true
11707      *
11708      * _.isInteger(Number.MIN_VALUE);
11709      * // => false
11710      *
11711      * _.isInteger(Infinity);
11712      * // => false
11713      *
11714      * _.isInteger('3');
11715      * // => false
11716      */
11717     function isInteger(value) {
11718       return typeof value == 'number' && value == toInteger(value);
11719     }
11720
11721     /**
11722      * Checks if `value` is a valid array-like length.
11723      *
11724      * **Note:** This method is loosely based on
11725      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11726      *
11727      * @static
11728      * @memberOf _
11729      * @since 4.0.0
11730      * @category Lang
11731      * @param {*} value The value to check.
11732      * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11733      * @example
11734      *
11735      * _.isLength(3);
11736      * // => true
11737      *
11738      * _.isLength(Number.MIN_VALUE);
11739      * // => false
11740      *
11741      * _.isLength(Infinity);
11742      * // => false
11743      *
11744      * _.isLength('3');
11745      * // => false
11746      */
11747     function isLength(value) {
11748       return typeof value == 'number' &&
11749         value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11750     }
11751
11752     /**
11753      * Checks if `value` is the
11754      * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11755      * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11756      *
11757      * @static
11758      * @memberOf _
11759      * @since 0.1.0
11760      * @category Lang
11761      * @param {*} value The value to check.
11762      * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11763      * @example
11764      *
11765      * _.isObject({});
11766      * // => true
11767      *
11768      * _.isObject([1, 2, 3]);
11769      * // => true
11770      *
11771      * _.isObject(_.noop);
11772      * // => true
11773      *
11774      * _.isObject(null);
11775      * // => false
11776      */
11777     function isObject(value) {
11778       var type = typeof value;
11779       return value != null && (type == 'object' || type == 'function');
11780     }
11781
11782     /**
11783      * Checks if `value` is object-like. A value is object-like if it's not `null`
11784      * and has a `typeof` result of "object".
11785      *
11786      * @static
11787      * @memberOf _
11788      * @since 4.0.0
11789      * @category Lang
11790      * @param {*} value The value to check.
11791      * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11792      * @example
11793      *
11794      * _.isObjectLike({});
11795      * // => true
11796      *
11797      * _.isObjectLike([1, 2, 3]);
11798      * // => true
11799      *
11800      * _.isObjectLike(_.noop);
11801      * // => false
11802      *
11803      * _.isObjectLike(null);
11804      * // => false
11805      */
11806     function isObjectLike(value) {
11807       return value != null && typeof value == 'object';
11808     }
11809
11810     /**
11811      * Checks if `value` is classified as a `Map` object.
11812      *
11813      * @static
11814      * @memberOf _
11815      * @since 4.3.0
11816      * @category Lang
11817      * @param {*} value The value to check.
11818      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11819      * @example
11820      *
11821      * _.isMap(new Map);
11822      * // => true
11823      *
11824      * _.isMap(new WeakMap);
11825      * // => false
11826      */
11827     var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11828
11829     /**
11830      * Performs a partial deep comparison between `object` and `source` to
11831      * determine if `object` contains equivalent property values.
11832      *
11833      * **Note:** This method is equivalent to `_.matches` when `source` is
11834      * partially applied.
11835      *
11836      * Partial comparisons will match empty array and empty object `source`
11837      * values against any array or object value, respectively. See `_.isEqual`
11838      * for a list of supported value comparisons.
11839      *
11840      * @static
11841      * @memberOf _
11842      * @since 3.0.0
11843      * @category Lang
11844      * @param {Object} object The object to inspect.
11845      * @param {Object} source The object of property values to match.
11846      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11847      * @example
11848      *
11849      * var object = { 'a': 1, 'b': 2 };
11850      *
11851      * _.isMatch(object, { 'b': 2 });
11852      * // => true
11853      *
11854      * _.isMatch(object, { 'b': 1 });
11855      * // => false
11856      */
11857     function isMatch(object, source) {
11858       return object === source || baseIsMatch(object, source, getMatchData(source));
11859     }
11860
11861     /**
11862      * This method is like `_.isMatch` except that it accepts `customizer` which
11863      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11864      * are handled by the method instead. The `customizer` is invoked with five
11865      * arguments: (objValue, srcValue, index|key, object, source).
11866      *
11867      * @static
11868      * @memberOf _
11869      * @since 4.0.0
11870      * @category Lang
11871      * @param {Object} object The object to inspect.
11872      * @param {Object} source The object of property values to match.
11873      * @param {Function} [customizer] The function to customize comparisons.
11874      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11875      * @example
11876      *
11877      * function isGreeting(value) {
11878      *   return /^h(?:i|ello)$/.test(value);
11879      * }
11880      *
11881      * function customizer(objValue, srcValue) {
11882      *   if (isGreeting(objValue) && isGreeting(srcValue)) {
11883      *     return true;
11884      *   }
11885      * }
11886      *
11887      * var object = { 'greeting': 'hello' };
11888      * var source = { 'greeting': 'hi' };
11889      *
11890      * _.isMatchWith(object, source, customizer);
11891      * // => true
11892      */
11893     function isMatchWith(object, source, customizer) {
11894       customizer = typeof customizer == 'function' ? customizer : undefined;
11895       return baseIsMatch(object, source, getMatchData(source), customizer);
11896     }
11897
11898     /**
11899      * Checks if `value` is `NaN`.
11900      *
11901      * **Note:** This method is based on
11902      * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11903      * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11904      * `undefined` and other non-number values.
11905      *
11906      * @static
11907      * @memberOf _
11908      * @since 0.1.0
11909      * @category Lang
11910      * @param {*} value The value to check.
11911      * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11912      * @example
11913      *
11914      * _.isNaN(NaN);
11915      * // => true
11916      *
11917      * _.isNaN(new Number(NaN));
11918      * // => true
11919      *
11920      * isNaN(undefined);
11921      * // => true
11922      *
11923      * _.isNaN(undefined);
11924      * // => false
11925      */
11926     function isNaN(value) {
11927       // An `NaN` primitive is the only value that is not equal to itself.
11928       // Perform the `toStringTag` check first to avoid errors with some
11929       // ActiveX objects in IE.
11930       return isNumber(value) && value != +value;
11931     }
11932
11933     /**
11934      * Checks if `value` is a pristine native function.
11935      *
11936      * **Note:** This method can't reliably detect native functions in the presence
11937      * of the core-js package because core-js circumvents this kind of detection.
11938      * Despite multiple requests, the core-js maintainer has made it clear: any
11939      * attempt to fix the detection will be obstructed. As a result, we're left
11940      * with little choice but to throw an error. Unfortunately, this also affects
11941      * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11942      * which rely on core-js.
11943      *
11944      * @static
11945      * @memberOf _
11946      * @since 3.0.0
11947      * @category Lang
11948      * @param {*} value The value to check.
11949      * @returns {boolean} Returns `true` if `value` is a native function,
11950      *  else `false`.
11951      * @example
11952      *
11953      * _.isNative(Array.prototype.push);
11954      * // => true
11955      *
11956      * _.isNative(_);
11957      * // => false
11958      */
11959     function isNative(value) {
11960       if (isMaskable(value)) {
11961         throw new Error(CORE_ERROR_TEXT);
11962       }
11963       return baseIsNative(value);
11964     }
11965
11966     /**
11967      * Checks if `value` is `null`.
11968      *
11969      * @static
11970      * @memberOf _
11971      * @since 0.1.0
11972      * @category Lang
11973      * @param {*} value The value to check.
11974      * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11975      * @example
11976      *
11977      * _.isNull(null);
11978      * // => true
11979      *
11980      * _.isNull(void 0);
11981      * // => false
11982      */
11983     function isNull(value) {
11984       return value === null;
11985     }
11986
11987     /**
11988      * Checks if `value` is `null` or `undefined`.
11989      *
11990      * @static
11991      * @memberOf _
11992      * @since 4.0.0
11993      * @category Lang
11994      * @param {*} value The value to check.
11995      * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
11996      * @example
11997      *
11998      * _.isNil(null);
11999      * // => true
12000      *
12001      * _.isNil(void 0);
12002      * // => true
12003      *
12004      * _.isNil(NaN);
12005      * // => false
12006      */
12007     function isNil(value) {
12008       return value == null;
12009     }
12010
12011     /**
12012      * Checks if `value` is classified as a `Number` primitive or object.
12013      *
12014      * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12015      * classified as numbers, use the `_.isFinite` method.
12016      *
12017      * @static
12018      * @memberOf _
12019      * @since 0.1.0
12020      * @category Lang
12021      * @param {*} value The value to check.
12022      * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12023      * @example
12024      *
12025      * _.isNumber(3);
12026      * // => true
12027      *
12028      * _.isNumber(Number.MIN_VALUE);
12029      * // => true
12030      *
12031      * _.isNumber(Infinity);
12032      * // => true
12033      *
12034      * _.isNumber('3');
12035      * // => false
12036      */
12037     function isNumber(value) {
12038       return typeof value == 'number' ||
12039         (isObjectLike(value) && baseGetTag(value) == numberTag);
12040     }
12041
12042     /**
12043      * Checks if `value` is a plain object, that is, an object created by the
12044      * `Object` constructor or one with a `[[Prototype]]` of `null`.
12045      *
12046      * @static
12047      * @memberOf _
12048      * @since 0.8.0
12049      * @category Lang
12050      * @param {*} value The value to check.
12051      * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12052      * @example
12053      *
12054      * function Foo() {
12055      *   this.a = 1;
12056      * }
12057      *
12058      * _.isPlainObject(new Foo);
12059      * // => false
12060      *
12061      * _.isPlainObject([1, 2, 3]);
12062      * // => false
12063      *
12064      * _.isPlainObject({ 'x': 0, 'y': 0 });
12065      * // => true
12066      *
12067      * _.isPlainObject(Object.create(null));
12068      * // => true
12069      */
12070     function isPlainObject(value) {
12071       if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12072         return false;
12073       }
12074       var proto = getPrototype(value);
12075       if (proto === null) {
12076         return true;
12077       }
12078       var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12079       return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12080         funcToString.call(Ctor) == objectCtorString;
12081     }
12082
12083     /**
12084      * Checks if `value` is classified as a `RegExp` object.
12085      *
12086      * @static
12087      * @memberOf _
12088      * @since 0.1.0
12089      * @category Lang
12090      * @param {*} value The value to check.
12091      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12092      * @example
12093      *
12094      * _.isRegExp(/abc/);
12095      * // => true
12096      *
12097      * _.isRegExp('/abc/');
12098      * // => false
12099      */
12100     var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12101
12102     /**
12103      * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12104      * double precision number which isn't the result of a rounded unsafe integer.
12105      *
12106      * **Note:** This method is based on
12107      * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12108      *
12109      * @static
12110      * @memberOf _
12111      * @since 4.0.0
12112      * @category Lang
12113      * @param {*} value The value to check.
12114      * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12115      * @example
12116      *
12117      * _.isSafeInteger(3);
12118      * // => true
12119      *
12120      * _.isSafeInteger(Number.MIN_VALUE);
12121      * // => false
12122      *
12123      * _.isSafeInteger(Infinity);
12124      * // => false
12125      *
12126      * _.isSafeInteger('3');
12127      * // => false
12128      */
12129     function isSafeInteger(value) {
12130       return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12131     }
12132
12133     /**
12134      * Checks if `value` is classified as a `Set` object.
12135      *
12136      * @static
12137      * @memberOf _
12138      * @since 4.3.0
12139      * @category Lang
12140      * @param {*} value The value to check.
12141      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12142      * @example
12143      *
12144      * _.isSet(new Set);
12145      * // => true
12146      *
12147      * _.isSet(new WeakSet);
12148      * // => false
12149      */
12150     var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12151
12152     /**
12153      * Checks if `value` is classified as a `String` primitive or object.
12154      *
12155      * @static
12156      * @since 0.1.0
12157      * @memberOf _
12158      * @category Lang
12159      * @param {*} value The value to check.
12160      * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12161      * @example
12162      *
12163      * _.isString('abc');
12164      * // => true
12165      *
12166      * _.isString(1);
12167      * // => false
12168      */
12169     function isString(value) {
12170       return typeof value == 'string' ||
12171         (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12172     }
12173
12174     /**
12175      * Checks if `value` is classified as a `Symbol` primitive or object.
12176      *
12177      * @static
12178      * @memberOf _
12179      * @since 4.0.0
12180      * @category Lang
12181      * @param {*} value The value to check.
12182      * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12183      * @example
12184      *
12185      * _.isSymbol(Symbol.iterator);
12186      * // => true
12187      *
12188      * _.isSymbol('abc');
12189      * // => false
12190      */
12191     function isSymbol(value) {
12192       return typeof value == 'symbol' ||
12193         (isObjectLike(value) && baseGetTag(value) == symbolTag);
12194     }
12195
12196     /**
12197      * Checks if `value` is classified as a typed array.
12198      *
12199      * @static
12200      * @memberOf _
12201      * @since 3.0.0
12202      * @category Lang
12203      * @param {*} value The value to check.
12204      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12205      * @example
12206      *
12207      * _.isTypedArray(new Uint8Array);
12208      * // => true
12209      *
12210      * _.isTypedArray([]);
12211      * // => false
12212      */
12213     var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12214
12215     /**
12216      * Checks if `value` is `undefined`.
12217      *
12218      * @static
12219      * @since 0.1.0
12220      * @memberOf _
12221      * @category Lang
12222      * @param {*} value The value to check.
12223      * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12224      * @example
12225      *
12226      * _.isUndefined(void 0);
12227      * // => true
12228      *
12229      * _.isUndefined(null);
12230      * // => false
12231      */
12232     function isUndefined(value) {
12233       return value === undefined;
12234     }
12235
12236     /**
12237      * Checks if `value` is classified as a `WeakMap` object.
12238      *
12239      * @static
12240      * @memberOf _
12241      * @since 4.3.0
12242      * @category Lang
12243      * @param {*} value The value to check.
12244      * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12245      * @example
12246      *
12247      * _.isWeakMap(new WeakMap);
12248      * // => true
12249      *
12250      * _.isWeakMap(new Map);
12251      * // => false
12252      */
12253     function isWeakMap(value) {
12254       return isObjectLike(value) && getTag(value) == weakMapTag;
12255     }
12256
12257     /**
12258      * Checks if `value` is classified as a `WeakSet` object.
12259      *
12260      * @static
12261      * @memberOf _
12262      * @since 4.3.0
12263      * @category Lang
12264      * @param {*} value The value to check.
12265      * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12266      * @example
12267      *
12268      * _.isWeakSet(new WeakSet);
12269      * // => true
12270      *
12271      * _.isWeakSet(new Set);
12272      * // => false
12273      */
12274     function isWeakSet(value) {
12275       return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12276     }
12277
12278     /**
12279      * Checks if `value` is less than `other`.
12280      *
12281      * @static
12282      * @memberOf _
12283      * @since 3.9.0
12284      * @category Lang
12285      * @param {*} value The value to compare.
12286      * @param {*} other The other value to compare.
12287      * @returns {boolean} Returns `true` if `value` is less than `other`,
12288      *  else `false`.
12289      * @see _.gt
12290      * @example
12291      *
12292      * _.lt(1, 3);
12293      * // => true
12294      *
12295      * _.lt(3, 3);
12296      * // => false
12297      *
12298      * _.lt(3, 1);
12299      * // => false
12300      */
12301     var lt = createRelationalOperation(baseLt);
12302
12303     /**
12304      * Checks if `value` is less than or equal to `other`.
12305      *
12306      * @static
12307      * @memberOf _
12308      * @since 3.9.0
12309      * @category Lang
12310      * @param {*} value The value to compare.
12311      * @param {*} other The other value to compare.
12312      * @returns {boolean} Returns `true` if `value` is less than or equal to
12313      *  `other`, else `false`.
12314      * @see _.gte
12315      * @example
12316      *
12317      * _.lte(1, 3);
12318      * // => true
12319      *
12320      * _.lte(3, 3);
12321      * // => true
12322      *
12323      * _.lte(3, 1);
12324      * // => false
12325      */
12326     var lte = createRelationalOperation(function(value, other) {
12327       return value <= other;
12328     });
12329
12330     /**
12331      * Converts `value` to an array.
12332      *
12333      * @static
12334      * @since 0.1.0
12335      * @memberOf _
12336      * @category Lang
12337      * @param {*} value The value to convert.
12338      * @returns {Array} Returns the converted array.
12339      * @example
12340      *
12341      * _.toArray({ 'a': 1, 'b': 2 });
12342      * // => [1, 2]
12343      *
12344      * _.toArray('abc');
12345      * // => ['a', 'b', 'c']
12346      *
12347      * _.toArray(1);
12348      * // => []
12349      *
12350      * _.toArray(null);
12351      * // => []
12352      */
12353     function toArray(value) {
12354       if (!value) {
12355         return [];
12356       }
12357       if (isArrayLike(value)) {
12358         return isString(value) ? stringToArray(value) : copyArray(value);
12359       }
12360       if (symIterator && value[symIterator]) {
12361         return iteratorToArray(value[symIterator]());
12362       }
12363       var tag = getTag(value),
12364           func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12365
12366       return func(value);
12367     }
12368
12369     /**
12370      * Converts `value` to a finite number.
12371      *
12372      * @static
12373      * @memberOf _
12374      * @since 4.12.0
12375      * @category Lang
12376      * @param {*} value The value to convert.
12377      * @returns {number} Returns the converted number.
12378      * @example
12379      *
12380      * _.toFinite(3.2);
12381      * // => 3.2
12382      *
12383      * _.toFinite(Number.MIN_VALUE);
12384      * // => 5e-324
12385      *
12386      * _.toFinite(Infinity);
12387      * // => 1.7976931348623157e+308
12388      *
12389      * _.toFinite('3.2');
12390      * // => 3.2
12391      */
12392     function toFinite(value) {
12393       if (!value) {
12394         return value === 0 ? value : 0;
12395       }
12396       value = toNumber(value);
12397       if (value === INFINITY || value === -INFINITY) {
12398         var sign = (value < 0 ? -1 : 1);
12399         return sign * MAX_INTEGER;
12400       }
12401       return value === value ? value : 0;
12402     }
12403
12404     /**
12405      * Converts `value` to an integer.
12406      *
12407      * **Note:** This method is loosely based on
12408      * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12409      *
12410      * @static
12411      * @memberOf _
12412      * @since 4.0.0
12413      * @category Lang
12414      * @param {*} value The value to convert.
12415      * @returns {number} Returns the converted integer.
12416      * @example
12417      *
12418      * _.toInteger(3.2);
12419      * // => 3
12420      *
12421      * _.toInteger(Number.MIN_VALUE);
12422      * // => 0
12423      *
12424      * _.toInteger(Infinity);
12425      * // => 1.7976931348623157e+308
12426      *
12427      * _.toInteger('3.2');
12428      * // => 3
12429      */
12430     function toInteger(value) {
12431       var result = toFinite(value),
12432           remainder = result % 1;
12433
12434       return result === result ? (remainder ? result - remainder : result) : 0;
12435     }
12436
12437     /**
12438      * Converts `value` to an integer suitable for use as the length of an
12439      * array-like object.
12440      *
12441      * **Note:** This method is based on
12442      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12443      *
12444      * @static
12445      * @memberOf _
12446      * @since 4.0.0
12447      * @category Lang
12448      * @param {*} value The value to convert.
12449      * @returns {number} Returns the converted integer.
12450      * @example
12451      *
12452      * _.toLength(3.2);
12453      * // => 3
12454      *
12455      * _.toLength(Number.MIN_VALUE);
12456      * // => 0
12457      *
12458      * _.toLength(Infinity);
12459      * // => 4294967295
12460      *
12461      * _.toLength('3.2');
12462      * // => 3
12463      */
12464     function toLength(value) {
12465       return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12466     }
12467
12468     /**
12469      * Converts `value` to a number.
12470      *
12471      * @static
12472      * @memberOf _
12473      * @since 4.0.0
12474      * @category Lang
12475      * @param {*} value The value to process.
12476      * @returns {number} Returns the number.
12477      * @example
12478      *
12479      * _.toNumber(3.2);
12480      * // => 3.2
12481      *
12482      * _.toNumber(Number.MIN_VALUE);
12483      * // => 5e-324
12484      *
12485      * _.toNumber(Infinity);
12486      * // => Infinity
12487      *
12488      * _.toNumber('3.2');
12489      * // => 3.2
12490      */
12491     function toNumber(value) {
12492       if (typeof value == 'number') {
12493         return value;
12494       }
12495       if (isSymbol(value)) {
12496         return NAN;
12497       }
12498       if (isObject(value)) {
12499         var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12500         value = isObject(other) ? (other + '') : other;
12501       }
12502       if (typeof value != 'string') {
12503         return value === 0 ? value : +value;
12504       }
12505       value = value.replace(reTrim, '');
12506       var isBinary = reIsBinary.test(value);
12507       return (isBinary || reIsOctal.test(value))
12508         ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12509         : (reIsBadHex.test(value) ? NAN : +value);
12510     }
12511
12512     /**
12513      * Converts `value` to a plain object flattening inherited enumerable string
12514      * keyed properties of `value` to own properties of the plain object.
12515      *
12516      * @static
12517      * @memberOf _
12518      * @since 3.0.0
12519      * @category Lang
12520      * @param {*} value The value to convert.
12521      * @returns {Object} Returns the converted plain object.
12522      * @example
12523      *
12524      * function Foo() {
12525      *   this.b = 2;
12526      * }
12527      *
12528      * Foo.prototype.c = 3;
12529      *
12530      * _.assign({ 'a': 1 }, new Foo);
12531      * // => { 'a': 1, 'b': 2 }
12532      *
12533      * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12534      * // => { 'a': 1, 'b': 2, 'c': 3 }
12535      */
12536     function toPlainObject(value) {
12537       return copyObject(value, keysIn(value));
12538     }
12539
12540     /**
12541      * Converts `value` to a safe integer. A safe integer can be compared and
12542      * represented correctly.
12543      *
12544      * @static
12545      * @memberOf _
12546      * @since 4.0.0
12547      * @category Lang
12548      * @param {*} value The value to convert.
12549      * @returns {number} Returns the converted integer.
12550      * @example
12551      *
12552      * _.toSafeInteger(3.2);
12553      * // => 3
12554      *
12555      * _.toSafeInteger(Number.MIN_VALUE);
12556      * // => 0
12557      *
12558      * _.toSafeInteger(Infinity);
12559      * // => 9007199254740991
12560      *
12561      * _.toSafeInteger('3.2');
12562      * // => 3
12563      */
12564     function toSafeInteger(value) {
12565       return value
12566         ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
12567         : (value === 0 ? value : 0);
12568     }
12569
12570     /**
12571      * Converts `value` to a string. An empty string is returned for `null`
12572      * and `undefined` values. The sign of `-0` is preserved.
12573      *
12574      * @static
12575      * @memberOf _
12576      * @since 4.0.0
12577      * @category Lang
12578      * @param {*} value The value to convert.
12579      * @returns {string} Returns the converted string.
12580      * @example
12581      *
12582      * _.toString(null);
12583      * // => ''
12584      *
12585      * _.toString(-0);
12586      * // => '-0'
12587      *
12588      * _.toString([1, 2, 3]);
12589      * // => '1,2,3'
12590      */
12591     function toString(value) {
12592       return value == null ? '' : baseToString(value);
12593     }
12594
12595     /*------------------------------------------------------------------------*/
12596
12597     /**
12598      * Assigns own enumerable string keyed properties of source objects to the
12599      * destination object. Source objects are applied from left to right.
12600      * Subsequent sources overwrite property assignments of previous sources.
12601      *
12602      * **Note:** This method mutates `object` and is loosely based on
12603      * [`Object.assign`](https://mdn.io/Object/assign).
12604      *
12605      * @static
12606      * @memberOf _
12607      * @since 0.10.0
12608      * @category Object
12609      * @param {Object} object The destination object.
12610      * @param {...Object} [sources] The source objects.
12611      * @returns {Object} Returns `object`.
12612      * @see _.assignIn
12613      * @example
12614      *
12615      * function Foo() {
12616      *   this.a = 1;
12617      * }
12618      *
12619      * function Bar() {
12620      *   this.c = 3;
12621      * }
12622      *
12623      * Foo.prototype.b = 2;
12624      * Bar.prototype.d = 4;
12625      *
12626      * _.assign({ 'a': 0 }, new Foo, new Bar);
12627      * // => { 'a': 1, 'c': 3 }
12628      */
12629     var assign = createAssigner(function(object, source) {
12630       if (isPrototype(source) || isArrayLike(source)) {
12631         copyObject(source, keys(source), object);
12632         return;
12633       }
12634       for (var key in source) {
12635         if (hasOwnProperty.call(source, key)) {
12636           assignValue(object, key, source[key]);
12637         }
12638       }
12639     });
12640
12641     /**
12642      * This method is like `_.assign` except that it iterates over own and
12643      * inherited source properties.
12644      *
12645      * **Note:** This method mutates `object`.
12646      *
12647      * @static
12648      * @memberOf _
12649      * @since 4.0.0
12650      * @alias extend
12651      * @category Object
12652      * @param {Object} object The destination object.
12653      * @param {...Object} [sources] The source objects.
12654      * @returns {Object} Returns `object`.
12655      * @see _.assign
12656      * @example
12657      *
12658      * function Foo() {
12659      *   this.a = 1;
12660      * }
12661      *
12662      * function Bar() {
12663      *   this.c = 3;
12664      * }
12665      *
12666      * Foo.prototype.b = 2;
12667      * Bar.prototype.d = 4;
12668      *
12669      * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12670      * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12671      */
12672     var assignIn = createAssigner(function(object, source) {
12673       copyObject(source, keysIn(source), object);
12674     });
12675
12676     /**
12677      * This method is like `_.assignIn` except that it accepts `customizer`
12678      * which is invoked to produce the assigned values. If `customizer` returns
12679      * `undefined`, assignment is handled by the method instead. The `customizer`
12680      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12681      *
12682      * **Note:** This method mutates `object`.
12683      *
12684      * @static
12685      * @memberOf _
12686      * @since 4.0.0
12687      * @alias extendWith
12688      * @category Object
12689      * @param {Object} object The destination object.
12690      * @param {...Object} sources The source objects.
12691      * @param {Function} [customizer] The function to customize assigned values.
12692      * @returns {Object} Returns `object`.
12693      * @see _.assignWith
12694      * @example
12695      *
12696      * function customizer(objValue, srcValue) {
12697      *   return _.isUndefined(objValue) ? srcValue : objValue;
12698      * }
12699      *
12700      * var defaults = _.partialRight(_.assignInWith, customizer);
12701      *
12702      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12703      * // => { 'a': 1, 'b': 2 }
12704      */
12705     var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12706       copyObject(source, keysIn(source), object, customizer);
12707     });
12708
12709     /**
12710      * This method is like `_.assign` except that it accepts `customizer`
12711      * which is invoked to produce the assigned values. If `customizer` returns
12712      * `undefined`, assignment is handled by the method instead. The `customizer`
12713      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12714      *
12715      * **Note:** This method mutates `object`.
12716      *
12717      * @static
12718      * @memberOf _
12719      * @since 4.0.0
12720      * @category Object
12721      * @param {Object} object The destination object.
12722      * @param {...Object} sources The source objects.
12723      * @param {Function} [customizer] The function to customize assigned values.
12724      * @returns {Object} Returns `object`.
12725      * @see _.assignInWith
12726      * @example
12727      *
12728      * function customizer(objValue, srcValue) {
12729      *   return _.isUndefined(objValue) ? srcValue : objValue;
12730      * }
12731      *
12732      * var defaults = _.partialRight(_.assignWith, customizer);
12733      *
12734      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12735      * // => { 'a': 1, 'b': 2 }
12736      */
12737     var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12738       copyObject(source, keys(source), object, customizer);
12739     });
12740
12741     /**
12742      * Creates an array of values corresponding to `paths` of `object`.
12743      *
12744      * @static
12745      * @memberOf _
12746      * @since 1.0.0
12747      * @category Object
12748      * @param {Object} object The object to iterate over.
12749      * @param {...(string|string[])} [paths] The property paths to pick.
12750      * @returns {Array} Returns the picked values.
12751      * @example
12752      *
12753      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12754      *
12755      * _.at(object, ['a[0].b.c', 'a[1]']);
12756      * // => [3, 4]
12757      */
12758     var at = flatRest(baseAt);
12759
12760     /**
12761      * Creates an object that inherits from the `prototype` object. If a
12762      * `properties` object is given, its own enumerable string keyed properties
12763      * are assigned to the created object.
12764      *
12765      * @static
12766      * @memberOf _
12767      * @since 2.3.0
12768      * @category Object
12769      * @param {Object} prototype The object to inherit from.
12770      * @param {Object} [properties] The properties to assign to the object.
12771      * @returns {Object} Returns the new object.
12772      * @example
12773      *
12774      * function Shape() {
12775      *   this.x = 0;
12776      *   this.y = 0;
12777      * }
12778      *
12779      * function Circle() {
12780      *   Shape.call(this);
12781      * }
12782      *
12783      * Circle.prototype = _.create(Shape.prototype, {
12784      *   'constructor': Circle
12785      * });
12786      *
12787      * var circle = new Circle;
12788      * circle instanceof Circle;
12789      * // => true
12790      *
12791      * circle instanceof Shape;
12792      * // => true
12793      */
12794     function create(prototype, properties) {
12795       var result = baseCreate(prototype);
12796       return properties == null ? result : baseAssign(result, properties);
12797     }
12798
12799     /**
12800      * Assigns own and inherited enumerable string keyed properties of source
12801      * objects to the destination object for all destination properties that
12802      * resolve to `undefined`. Source objects are applied from left to right.
12803      * Once a property is set, additional values of the same property are ignored.
12804      *
12805      * **Note:** This method mutates `object`.
12806      *
12807      * @static
12808      * @since 0.1.0
12809      * @memberOf _
12810      * @category Object
12811      * @param {Object} object The destination object.
12812      * @param {...Object} [sources] The source objects.
12813      * @returns {Object} Returns `object`.
12814      * @see _.defaultsDeep
12815      * @example
12816      *
12817      * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12818      * // => { 'a': 1, 'b': 2 }
12819      */
12820     var defaults = baseRest(function(args) {
12821       args.push(undefined, customDefaultsAssignIn);
12822       return apply(assignInWith, undefined, args);
12823     });
12824
12825     /**
12826      * This method is like `_.defaults` except that it recursively assigns
12827      * default properties.
12828      *
12829      * **Note:** This method mutates `object`.
12830      *
12831      * @static
12832      * @memberOf _
12833      * @since 3.10.0
12834      * @category Object
12835      * @param {Object} object The destination object.
12836      * @param {...Object} [sources] The source objects.
12837      * @returns {Object} Returns `object`.
12838      * @see _.defaults
12839      * @example
12840      *
12841      * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12842      * // => { 'a': { 'b': 2, 'c': 3 } }
12843      */
12844     var defaultsDeep = baseRest(function(args) {
12845       args.push(undefined, customDefaultsMerge);
12846       return apply(mergeWith, undefined, args);
12847     });
12848
12849     /**
12850      * This method is like `_.find` except that it returns the key of the first
12851      * element `predicate` returns truthy for instead of the element itself.
12852      *
12853      * @static
12854      * @memberOf _
12855      * @since 1.1.0
12856      * @category Object
12857      * @param {Object} object The object to inspect.
12858      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12859      * @returns {string|undefined} Returns the key of the matched element,
12860      *  else `undefined`.
12861      * @example
12862      *
12863      * var users = {
12864      *   'barney':  { 'age': 36, 'active': true },
12865      *   'fred':    { 'age': 40, 'active': false },
12866      *   'pebbles': { 'age': 1,  'active': true }
12867      * };
12868      *
12869      * _.findKey(users, function(o) { return o.age < 40; });
12870      * // => 'barney' (iteration order is not guaranteed)
12871      *
12872      * // The `_.matches` iteratee shorthand.
12873      * _.findKey(users, { 'age': 1, 'active': true });
12874      * // => 'pebbles'
12875      *
12876      * // The `_.matchesProperty` iteratee shorthand.
12877      * _.findKey(users, ['active', false]);
12878      * // => 'fred'
12879      *
12880      * // The `_.property` iteratee shorthand.
12881      * _.findKey(users, 'active');
12882      * // => 'barney'
12883      */
12884     function findKey(object, predicate) {
12885       return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12886     }
12887
12888     /**
12889      * This method is like `_.findKey` except that it iterates over elements of
12890      * a collection in the opposite order.
12891      *
12892      * @static
12893      * @memberOf _
12894      * @since 2.0.0
12895      * @category Object
12896      * @param {Object} object The object to inspect.
12897      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12898      * @returns {string|undefined} Returns the key of the matched element,
12899      *  else `undefined`.
12900      * @example
12901      *
12902      * var users = {
12903      *   'barney':  { 'age': 36, 'active': true },
12904      *   'fred':    { 'age': 40, 'active': false },
12905      *   'pebbles': { 'age': 1,  'active': true }
12906      * };
12907      *
12908      * _.findLastKey(users, function(o) { return o.age < 40; });
12909      * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12910      *
12911      * // The `_.matches` iteratee shorthand.
12912      * _.findLastKey(users, { 'age': 36, 'active': true });
12913      * // => 'barney'
12914      *
12915      * // The `_.matchesProperty` iteratee shorthand.
12916      * _.findLastKey(users, ['active', false]);
12917      * // => 'fred'
12918      *
12919      * // The `_.property` iteratee shorthand.
12920      * _.findLastKey(users, 'active');
12921      * // => 'pebbles'
12922      */
12923     function findLastKey(object, predicate) {
12924       return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12925     }
12926
12927     /**
12928      * Iterates over own and inherited enumerable string keyed properties of an
12929      * object and invokes `iteratee` for each property. The iteratee is invoked
12930      * with three arguments: (value, key, object). Iteratee functions may exit
12931      * iteration early by explicitly returning `false`.
12932      *
12933      * @static
12934      * @memberOf _
12935      * @since 0.3.0
12936      * @category Object
12937      * @param {Object} object The object to iterate over.
12938      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12939      * @returns {Object} Returns `object`.
12940      * @see _.forInRight
12941      * @example
12942      *
12943      * function Foo() {
12944      *   this.a = 1;
12945      *   this.b = 2;
12946      * }
12947      *
12948      * Foo.prototype.c = 3;
12949      *
12950      * _.forIn(new Foo, function(value, key) {
12951      *   console.log(key);
12952      * });
12953      * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12954      */
12955     function forIn(object, iteratee) {
12956       return object == null
12957         ? object
12958         : baseFor(object, getIteratee(iteratee, 3), keysIn);
12959     }
12960
12961     /**
12962      * This method is like `_.forIn` except that it iterates over properties of
12963      * `object` in the opposite order.
12964      *
12965      * @static
12966      * @memberOf _
12967      * @since 2.0.0
12968      * @category Object
12969      * @param {Object} object The object to iterate over.
12970      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12971      * @returns {Object} Returns `object`.
12972      * @see _.forIn
12973      * @example
12974      *
12975      * function Foo() {
12976      *   this.a = 1;
12977      *   this.b = 2;
12978      * }
12979      *
12980      * Foo.prototype.c = 3;
12981      *
12982      * _.forInRight(new Foo, function(value, key) {
12983      *   console.log(key);
12984      * });
12985      * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12986      */
12987     function forInRight(object, iteratee) {
12988       return object == null
12989         ? object
12990         : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12991     }
12992
12993     /**
12994      * Iterates over own enumerable string keyed properties of an object and
12995      * invokes `iteratee` for each property. The iteratee is invoked with three
12996      * arguments: (value, key, object). Iteratee functions may exit iteration
12997      * early by explicitly returning `false`.
12998      *
12999      * @static
13000      * @memberOf _
13001      * @since 0.3.0
13002      * @category Object
13003      * @param {Object} object The object to iterate over.
13004      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13005      * @returns {Object} Returns `object`.
13006      * @see _.forOwnRight
13007      * @example
13008      *
13009      * function Foo() {
13010      *   this.a = 1;
13011      *   this.b = 2;
13012      * }
13013      *
13014      * Foo.prototype.c = 3;
13015      *
13016      * _.forOwn(new Foo, function(value, key) {
13017      *   console.log(key);
13018      * });
13019      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13020      */
13021     function forOwn(object, iteratee) {
13022       return object && baseForOwn(object, getIteratee(iteratee, 3));
13023     }
13024
13025     /**
13026      * This method is like `_.forOwn` except that it iterates over properties of
13027      * `object` in the opposite order.
13028      *
13029      * @static
13030      * @memberOf _
13031      * @since 2.0.0
13032      * @category Object
13033      * @param {Object} object The object to iterate over.
13034      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13035      * @returns {Object} Returns `object`.
13036      * @see _.forOwn
13037      * @example
13038      *
13039      * function Foo() {
13040      *   this.a = 1;
13041      *   this.b = 2;
13042      * }
13043      *
13044      * Foo.prototype.c = 3;
13045      *
13046      * _.forOwnRight(new Foo, function(value, key) {
13047      *   console.log(key);
13048      * });
13049      * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13050      */
13051     function forOwnRight(object, iteratee) {
13052       return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13053     }
13054
13055     /**
13056      * Creates an array of function property names from own enumerable properties
13057      * of `object`.
13058      *
13059      * @static
13060      * @since 0.1.0
13061      * @memberOf _
13062      * @category Object
13063      * @param {Object} object The object to inspect.
13064      * @returns {Array} Returns the function names.
13065      * @see _.functionsIn
13066      * @example
13067      *
13068      * function Foo() {
13069      *   this.a = _.constant('a');
13070      *   this.b = _.constant('b');
13071      * }
13072      *
13073      * Foo.prototype.c = _.constant('c');
13074      *
13075      * _.functions(new Foo);
13076      * // => ['a', 'b']
13077      */
13078     function functions(object) {
13079       return object == null ? [] : baseFunctions(object, keys(object));
13080     }
13081
13082     /**
13083      * Creates an array of function property names from own and inherited
13084      * enumerable properties of `object`.
13085      *
13086      * @static
13087      * @memberOf _
13088      * @since 4.0.0
13089      * @category Object
13090      * @param {Object} object The object to inspect.
13091      * @returns {Array} Returns the function names.
13092      * @see _.functions
13093      * @example
13094      *
13095      * function Foo() {
13096      *   this.a = _.constant('a');
13097      *   this.b = _.constant('b');
13098      * }
13099      *
13100      * Foo.prototype.c = _.constant('c');
13101      *
13102      * _.functionsIn(new Foo);
13103      * // => ['a', 'b', 'c']
13104      */
13105     function functionsIn(object) {
13106       return object == null ? [] : baseFunctions(object, keysIn(object));
13107     }
13108
13109     /**
13110      * Gets the value at `path` of `object`. If the resolved value is
13111      * `undefined`, the `defaultValue` is returned in its place.
13112      *
13113      * @static
13114      * @memberOf _
13115      * @since 3.7.0
13116      * @category Object
13117      * @param {Object} object The object to query.
13118      * @param {Array|string} path The path of the property to get.
13119      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13120      * @returns {*} Returns the resolved value.
13121      * @example
13122      *
13123      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13124      *
13125      * _.get(object, 'a[0].b.c');
13126      * // => 3
13127      *
13128      * _.get(object, ['a', '0', 'b', 'c']);
13129      * // => 3
13130      *
13131      * _.get(object, 'a.b.c', 'default');
13132      * // => 'default'
13133      */
13134     function get(object, path, defaultValue) {
13135       var result = object == null ? undefined : baseGet(object, path);
13136       return result === undefined ? defaultValue : result;
13137     }
13138
13139     /**
13140      * Checks if `path` is a direct property of `object`.
13141      *
13142      * @static
13143      * @since 0.1.0
13144      * @memberOf _
13145      * @category Object
13146      * @param {Object} object The object to query.
13147      * @param {Array|string} path The path to check.
13148      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13149      * @example
13150      *
13151      * var object = { 'a': { 'b': 2 } };
13152      * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13153      *
13154      * _.has(object, 'a');
13155      * // => true
13156      *
13157      * _.has(object, 'a.b');
13158      * // => true
13159      *
13160      * _.has(object, ['a', 'b']);
13161      * // => true
13162      *
13163      * _.has(other, 'a');
13164      * // => false
13165      */
13166     function has(object, path) {
13167       return object != null && hasPath(object, path, baseHas);
13168     }
13169
13170     /**
13171      * Checks if `path` is a direct or inherited property of `object`.
13172      *
13173      * @static
13174      * @memberOf _
13175      * @since 4.0.0
13176      * @category Object
13177      * @param {Object} object The object to query.
13178      * @param {Array|string} path The path to check.
13179      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13180      * @example
13181      *
13182      * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13183      *
13184      * _.hasIn(object, 'a');
13185      * // => true
13186      *
13187      * _.hasIn(object, 'a.b');
13188      * // => true
13189      *
13190      * _.hasIn(object, ['a', 'b']);
13191      * // => true
13192      *
13193      * _.hasIn(object, 'b');
13194      * // => false
13195      */
13196     function hasIn(object, path) {
13197       return object != null && hasPath(object, path, baseHasIn);
13198     }
13199
13200     /**
13201      * Creates an object composed of the inverted keys and values of `object`.
13202      * If `object` contains duplicate values, subsequent values overwrite
13203      * property assignments of previous values.
13204      *
13205      * @static
13206      * @memberOf _
13207      * @since 0.7.0
13208      * @category Object
13209      * @param {Object} object The object to invert.
13210      * @returns {Object} Returns the new inverted object.
13211      * @example
13212      *
13213      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13214      *
13215      * _.invert(object);
13216      * // => { '1': 'c', '2': 'b' }
13217      */
13218     var invert = createInverter(function(result, value, key) {
13219       result[value] = key;
13220     }, constant(identity));
13221
13222     /**
13223      * This method is like `_.invert` except that the inverted object is generated
13224      * from the results of running each element of `object` thru `iteratee`. The
13225      * corresponding inverted value of each inverted key is an array of keys
13226      * responsible for generating the inverted value. The iteratee is invoked
13227      * with one argument: (value).
13228      *
13229      * @static
13230      * @memberOf _
13231      * @since 4.1.0
13232      * @category Object
13233      * @param {Object} object The object to invert.
13234      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13235      * @returns {Object} Returns the new inverted object.
13236      * @example
13237      *
13238      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13239      *
13240      * _.invertBy(object);
13241      * // => { '1': ['a', 'c'], '2': ['b'] }
13242      *
13243      * _.invertBy(object, function(value) {
13244      *   return 'group' + value;
13245      * });
13246      * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13247      */
13248     var invertBy = createInverter(function(result, value, key) {
13249       if (hasOwnProperty.call(result, value)) {
13250         result[value].push(key);
13251       } else {
13252         result[value] = [key];
13253       }
13254     }, getIteratee);
13255
13256     /**
13257      * Invokes the method at `path` of `object`.
13258      *
13259      * @static
13260      * @memberOf _
13261      * @since 4.0.0
13262      * @category Object
13263      * @param {Object} object The object to query.
13264      * @param {Array|string} path The path of the method to invoke.
13265      * @param {...*} [args] The arguments to invoke the method with.
13266      * @returns {*} Returns the result of the invoked method.
13267      * @example
13268      *
13269      * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13270      *
13271      * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13272      * // => [2, 3]
13273      */
13274     var invoke = baseRest(baseInvoke);
13275
13276     /**
13277      * Creates an array of the own enumerable property names of `object`.
13278      *
13279      * **Note:** Non-object values are coerced to objects. See the
13280      * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13281      * for more details.
13282      *
13283      * @static
13284      * @since 0.1.0
13285      * @memberOf _
13286      * @category Object
13287      * @param {Object} object The object to query.
13288      * @returns {Array} Returns the array of property names.
13289      * @example
13290      *
13291      * function Foo() {
13292      *   this.a = 1;
13293      *   this.b = 2;
13294      * }
13295      *
13296      * Foo.prototype.c = 3;
13297      *
13298      * _.keys(new Foo);
13299      * // => ['a', 'b'] (iteration order is not guaranteed)
13300      *
13301      * _.keys('hi');
13302      * // => ['0', '1']
13303      */
13304     function keys(object) {
13305       return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13306     }
13307
13308     /**
13309      * Creates an array of the own and inherited enumerable property names of `object`.
13310      *
13311      * **Note:** Non-object values are coerced to objects.
13312      *
13313      * @static
13314      * @memberOf _
13315      * @since 3.0.0
13316      * @category Object
13317      * @param {Object} object The object to query.
13318      * @returns {Array} Returns the array of property names.
13319      * @example
13320      *
13321      * function Foo() {
13322      *   this.a = 1;
13323      *   this.b = 2;
13324      * }
13325      *
13326      * Foo.prototype.c = 3;
13327      *
13328      * _.keysIn(new Foo);
13329      * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13330      */
13331     function keysIn(object) {
13332       return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13333     }
13334
13335     /**
13336      * The opposite of `_.mapValues`; this method creates an object with the
13337      * same values as `object` and keys generated by running each own enumerable
13338      * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13339      * with three arguments: (value, key, object).
13340      *
13341      * @static
13342      * @memberOf _
13343      * @since 3.8.0
13344      * @category Object
13345      * @param {Object} object The object to iterate over.
13346      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13347      * @returns {Object} Returns the new mapped object.
13348      * @see _.mapValues
13349      * @example
13350      *
13351      * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13352      *   return key + value;
13353      * });
13354      * // => { 'a1': 1, 'b2': 2 }
13355      */
13356     function mapKeys(object, iteratee) {
13357       var result = {};
13358       iteratee = getIteratee(iteratee, 3);
13359
13360       baseForOwn(object, function(value, key, object) {
13361         baseAssignValue(result, iteratee(value, key, object), value);
13362       });
13363       return result;
13364     }
13365
13366     /**
13367      * Creates an object with the same keys as `object` and values generated
13368      * by running each own enumerable string keyed property of `object` thru
13369      * `iteratee`. The iteratee is invoked with three arguments:
13370      * (value, key, object).
13371      *
13372      * @static
13373      * @memberOf _
13374      * @since 2.4.0
13375      * @category Object
13376      * @param {Object} object The object to iterate over.
13377      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13378      * @returns {Object} Returns the new mapped object.
13379      * @see _.mapKeys
13380      * @example
13381      *
13382      * var users = {
13383      *   'fred':    { 'user': 'fred',    'age': 40 },
13384      *   'pebbles': { 'user': 'pebbles', 'age': 1 }
13385      * };
13386      *
13387      * _.mapValues(users, function(o) { return o.age; });
13388      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13389      *
13390      * // The `_.property` iteratee shorthand.
13391      * _.mapValues(users, 'age');
13392      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13393      */
13394     function mapValues(object, iteratee) {
13395       var result = {};
13396       iteratee = getIteratee(iteratee, 3);
13397
13398       baseForOwn(object, function(value, key, object) {
13399         baseAssignValue(result, key, iteratee(value, key, object));
13400       });
13401       return result;
13402     }
13403
13404     /**
13405      * This method is like `_.assign` except that it recursively merges own and
13406      * inherited enumerable string keyed properties of source objects into the
13407      * destination object. Source properties that resolve to `undefined` are
13408      * skipped if a destination value exists. Array and plain object properties
13409      * are merged recursively. Other objects and value types are overridden by
13410      * assignment. Source objects are applied from left to right. Subsequent
13411      * sources overwrite property assignments of previous sources.
13412      *
13413      * **Note:** This method mutates `object`.
13414      *
13415      * @static
13416      * @memberOf _
13417      * @since 0.5.0
13418      * @category Object
13419      * @param {Object} object The destination object.
13420      * @param {...Object} [sources] The source objects.
13421      * @returns {Object} Returns `object`.
13422      * @example
13423      *
13424      * var object = {
13425      *   'a': [{ 'b': 2 }, { 'd': 4 }]
13426      * };
13427      *
13428      * var other = {
13429      *   'a': [{ 'c': 3 }, { 'e': 5 }]
13430      * };
13431      *
13432      * _.merge(object, other);
13433      * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13434      */
13435     var merge = createAssigner(function(object, source, srcIndex) {
13436       baseMerge(object, source, srcIndex);
13437     });
13438
13439     /**
13440      * This method is like `_.merge` except that it accepts `customizer` which
13441      * is invoked to produce the merged values of the destination and source
13442      * properties. If `customizer` returns `undefined`, merging is handled by the
13443      * method instead. The `customizer` is invoked with six arguments:
13444      * (objValue, srcValue, key, object, source, stack).
13445      *
13446      * **Note:** This method mutates `object`.
13447      *
13448      * @static
13449      * @memberOf _
13450      * @since 4.0.0
13451      * @category Object
13452      * @param {Object} object The destination object.
13453      * @param {...Object} sources The source objects.
13454      * @param {Function} customizer The function to customize assigned values.
13455      * @returns {Object} Returns `object`.
13456      * @example
13457      *
13458      * function customizer(objValue, srcValue) {
13459      *   if (_.isArray(objValue)) {
13460      *     return objValue.concat(srcValue);
13461      *   }
13462      * }
13463      *
13464      * var object = { 'a': [1], 'b': [2] };
13465      * var other = { 'a': [3], 'b': [4] };
13466      *
13467      * _.mergeWith(object, other, customizer);
13468      * // => { 'a': [1, 3], 'b': [2, 4] }
13469      */
13470     var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13471       baseMerge(object, source, srcIndex, customizer);
13472     });
13473
13474     /**
13475      * The opposite of `_.pick`; this method creates an object composed of the
13476      * own and inherited enumerable property paths of `object` that are not omitted.
13477      *
13478      * **Note:** This method is considerably slower than `_.pick`.
13479      *
13480      * @static
13481      * @since 0.1.0
13482      * @memberOf _
13483      * @category Object
13484      * @param {Object} object The source object.
13485      * @param {...(string|string[])} [paths] The property paths to omit.
13486      * @returns {Object} Returns the new object.
13487      * @example
13488      *
13489      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13490      *
13491      * _.omit(object, ['a', 'c']);
13492      * // => { 'b': '2' }
13493      */
13494     var omit = flatRest(function(object, paths) {
13495       var result = {};
13496       if (object == null) {
13497         return result;
13498       }
13499       var isDeep = false;
13500       paths = arrayMap(paths, function(path) {
13501         path = castPath(path, object);
13502         isDeep || (isDeep = path.length > 1);
13503         return path;
13504       });
13505       copyObject(object, getAllKeysIn(object), result);
13506       if (isDeep) {
13507         result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
13508       }
13509       var length = paths.length;
13510       while (length--) {
13511         baseUnset(result, paths[length]);
13512       }
13513       return result;
13514     });
13515
13516     /**
13517      * The opposite of `_.pickBy`; this method creates an object composed of
13518      * the own and inherited enumerable string keyed properties of `object` that
13519      * `predicate` doesn't return truthy for. The predicate is invoked with two
13520      * arguments: (value, key).
13521      *
13522      * @static
13523      * @memberOf _
13524      * @since 4.0.0
13525      * @category Object
13526      * @param {Object} object The source object.
13527      * @param {Function} [predicate=_.identity] The function invoked per property.
13528      * @returns {Object} Returns the new object.
13529      * @example
13530      *
13531      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13532      *
13533      * _.omitBy(object, _.isNumber);
13534      * // => { 'b': '2' }
13535      */
13536     function omitBy(object, predicate) {
13537       return pickBy(object, negate(getIteratee(predicate)));
13538     }
13539
13540     /**
13541      * Creates an object composed of the picked `object` properties.
13542      *
13543      * @static
13544      * @since 0.1.0
13545      * @memberOf _
13546      * @category Object
13547      * @param {Object} object The source object.
13548      * @param {...(string|string[])} [paths] The property paths to pick.
13549      * @returns {Object} Returns the new object.
13550      * @example
13551      *
13552      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13553      *
13554      * _.pick(object, ['a', 'c']);
13555      * // => { 'a': 1, 'c': 3 }
13556      */
13557     var pick = flatRest(function(object, paths) {
13558       return object == null ? {} : basePick(object, paths);
13559     });
13560
13561     /**
13562      * Creates an object composed of the `object` properties `predicate` returns
13563      * truthy for. The predicate is invoked with two arguments: (value, key).
13564      *
13565      * @static
13566      * @memberOf _
13567      * @since 4.0.0
13568      * @category Object
13569      * @param {Object} object The source object.
13570      * @param {Function} [predicate=_.identity] The function invoked per property.
13571      * @returns {Object} Returns the new object.
13572      * @example
13573      *
13574      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13575      *
13576      * _.pickBy(object, _.isNumber);
13577      * // => { 'a': 1, 'c': 3 }
13578      */
13579     function pickBy(object, predicate) {
13580       if (object == null) {
13581         return {};
13582       }
13583       var props = arrayMap(getAllKeysIn(object), function(prop) {
13584         return [prop];
13585       });
13586       predicate = getIteratee(predicate);
13587       return basePickBy(object, props, function(value, path) {
13588         return predicate(value, path[0]);
13589       });
13590     }
13591
13592     /**
13593      * This method is like `_.get` except that if the resolved value is a
13594      * function it's invoked with the `this` binding of its parent object and
13595      * its result is returned.
13596      *
13597      * @static
13598      * @since 0.1.0
13599      * @memberOf _
13600      * @category Object
13601      * @param {Object} object The object to query.
13602      * @param {Array|string} path The path of the property to resolve.
13603      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13604      * @returns {*} Returns the resolved value.
13605      * @example
13606      *
13607      * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13608      *
13609      * _.result(object, 'a[0].b.c1');
13610      * // => 3
13611      *
13612      * _.result(object, 'a[0].b.c2');
13613      * // => 4
13614      *
13615      * _.result(object, 'a[0].b.c3', 'default');
13616      * // => 'default'
13617      *
13618      * _.result(object, 'a[0].b.c3', _.constant('default'));
13619      * // => 'default'
13620      */
13621     function result(object, path, defaultValue) {
13622       path = castPath(path, object);
13623
13624       var index = -1,
13625           length = path.length;
13626
13627       // Ensure the loop is entered when path is empty.
13628       if (!length) {
13629         length = 1;
13630         object = undefined;
13631       }
13632       while (++index < length) {
13633         var value = object == null ? undefined : object[toKey(path[index])];
13634         if (value === undefined) {
13635           index = length;
13636           value = defaultValue;
13637         }
13638         object = isFunction(value) ? value.call(object) : value;
13639       }
13640       return object;
13641     }
13642
13643     /**
13644      * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13645      * it's created. Arrays are created for missing index properties while objects
13646      * are created for all other missing properties. Use `_.setWith` to customize
13647      * `path` creation.
13648      *
13649      * **Note:** This method mutates `object`.
13650      *
13651      * @static
13652      * @memberOf _
13653      * @since 3.7.0
13654      * @category Object
13655      * @param {Object} object The object to modify.
13656      * @param {Array|string} path The path of the property to set.
13657      * @param {*} value The value to set.
13658      * @returns {Object} Returns `object`.
13659      * @example
13660      *
13661      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13662      *
13663      * _.set(object, 'a[0].b.c', 4);
13664      * console.log(object.a[0].b.c);
13665      * // => 4
13666      *
13667      * _.set(object, ['x', '0', 'y', 'z'], 5);
13668      * console.log(object.x[0].y.z);
13669      * // => 5
13670      */
13671     function set(object, path, value) {
13672       return object == null ? object : baseSet(object, path, value);
13673     }
13674
13675     /**
13676      * This method is like `_.set` except that it accepts `customizer` which is
13677      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13678      * path creation is handled by the method instead. The `customizer` is invoked
13679      * with three arguments: (nsValue, key, nsObject).
13680      *
13681      * **Note:** This method mutates `object`.
13682      *
13683      * @static
13684      * @memberOf _
13685      * @since 4.0.0
13686      * @category Object
13687      * @param {Object} object The object to modify.
13688      * @param {Array|string} path The path of the property to set.
13689      * @param {*} value The value to set.
13690      * @param {Function} [customizer] The function to customize assigned values.
13691      * @returns {Object} Returns `object`.
13692      * @example
13693      *
13694      * var object = {};
13695      *
13696      * _.setWith(object, '[0][1]', 'a', Object);
13697      * // => { '0': { '1': 'a' } }
13698      */
13699     function setWith(object, path, value, customizer) {
13700       customizer = typeof customizer == 'function' ? customizer : undefined;
13701       return object == null ? object : baseSet(object, path, value, customizer);
13702     }
13703
13704     /**
13705      * Creates an array of own enumerable string keyed-value pairs for `object`
13706      * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13707      * entries are returned.
13708      *
13709      * @static
13710      * @memberOf _
13711      * @since 4.0.0
13712      * @alias entries
13713      * @category Object
13714      * @param {Object} object The object to query.
13715      * @returns {Array} Returns the key-value pairs.
13716      * @example
13717      *
13718      * function Foo() {
13719      *   this.a = 1;
13720      *   this.b = 2;
13721      * }
13722      *
13723      * Foo.prototype.c = 3;
13724      *
13725      * _.toPairs(new Foo);
13726      * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13727      */
13728     var toPairs = createToPairs(keys);
13729
13730     /**
13731      * Creates an array of own and inherited enumerable string keyed-value pairs
13732      * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13733      * or set, its entries are returned.
13734      *
13735      * @static
13736      * @memberOf _
13737      * @since 4.0.0
13738      * @alias entriesIn
13739      * @category Object
13740      * @param {Object} object The object to query.
13741      * @returns {Array} Returns the key-value pairs.
13742      * @example
13743      *
13744      * function Foo() {
13745      *   this.a = 1;
13746      *   this.b = 2;
13747      * }
13748      *
13749      * Foo.prototype.c = 3;
13750      *
13751      * _.toPairsIn(new Foo);
13752      * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13753      */
13754     var toPairsIn = createToPairs(keysIn);
13755
13756     /**
13757      * An alternative to `_.reduce`; this method transforms `object` to a new
13758      * `accumulator` object which is the result of running each of its own
13759      * enumerable string keyed properties thru `iteratee`, with each invocation
13760      * potentially mutating the `accumulator` object. If `accumulator` is not
13761      * provided, a new object with the same `[[Prototype]]` will be used. The
13762      * iteratee is invoked with four arguments: (accumulator, value, key, object).
13763      * Iteratee functions may exit iteration early by explicitly returning `false`.
13764      *
13765      * @static
13766      * @memberOf _
13767      * @since 1.3.0
13768      * @category Object
13769      * @param {Object} object The object to iterate over.
13770      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13771      * @param {*} [accumulator] The custom accumulator value.
13772      * @returns {*} Returns the accumulated value.
13773      * @example
13774      *
13775      * _.transform([2, 3, 4], function(result, n) {
13776      *   result.push(n *= n);
13777      *   return n % 2 == 0;
13778      * }, []);
13779      * // => [4, 9]
13780      *
13781      * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13782      *   (result[value] || (result[value] = [])).push(key);
13783      * }, {});
13784      * // => { '1': ['a', 'c'], '2': ['b'] }
13785      */
13786     function transform(object, iteratee, accumulator) {
13787       var isArr = isArray(object),
13788           isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13789
13790       iteratee = getIteratee(iteratee, 4);
13791       if (accumulator == null) {
13792         var Ctor = object && object.constructor;
13793         if (isArrLike) {
13794           accumulator = isArr ? new Ctor : [];
13795         }
13796         else if (isObject(object)) {
13797           accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13798         }
13799         else {
13800           accumulator = {};
13801         }
13802       }
13803       (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13804         return iteratee(accumulator, value, index, object);
13805       });
13806       return accumulator;
13807     }
13808
13809     /**
13810      * Removes the property at `path` of `object`.
13811      *
13812      * **Note:** This method mutates `object`.
13813      *
13814      * @static
13815      * @memberOf _
13816      * @since 4.0.0
13817      * @category Object
13818      * @param {Object} object The object to modify.
13819      * @param {Array|string} path The path of the property to unset.
13820      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13821      * @example
13822      *
13823      * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13824      * _.unset(object, 'a[0].b.c');
13825      * // => true
13826      *
13827      * console.log(object);
13828      * // => { 'a': [{ 'b': {} }] };
13829      *
13830      * _.unset(object, ['a', '0', 'b', 'c']);
13831      * // => true
13832      *
13833      * console.log(object);
13834      * // => { 'a': [{ 'b': {} }] };
13835      */
13836     function unset(object, path) {
13837       return object == null ? true : baseUnset(object, path);
13838     }
13839
13840     /**
13841      * This method is like `_.set` except that accepts `updater` to produce the
13842      * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13843      * is invoked with one argument: (value).
13844      *
13845      * **Note:** This method mutates `object`.
13846      *
13847      * @static
13848      * @memberOf _
13849      * @since 4.6.0
13850      * @category Object
13851      * @param {Object} object The object to modify.
13852      * @param {Array|string} path The path of the property to set.
13853      * @param {Function} updater The function to produce the updated value.
13854      * @returns {Object} Returns `object`.
13855      * @example
13856      *
13857      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13858      *
13859      * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13860      * console.log(object.a[0].b.c);
13861      * // => 9
13862      *
13863      * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13864      * console.log(object.x[0].y.z);
13865      * // => 0
13866      */
13867     function update(object, path, updater) {
13868       return object == null ? object : baseUpdate(object, path, castFunction(updater));
13869     }
13870
13871     /**
13872      * This method is like `_.update` except that it accepts `customizer` which is
13873      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13874      * path creation is handled by the method instead. The `customizer` is invoked
13875      * with three arguments: (nsValue, key, nsObject).
13876      *
13877      * **Note:** This method mutates `object`.
13878      *
13879      * @static
13880      * @memberOf _
13881      * @since 4.6.0
13882      * @category Object
13883      * @param {Object} object The object to modify.
13884      * @param {Array|string} path The path of the property to set.
13885      * @param {Function} updater The function to produce the updated value.
13886      * @param {Function} [customizer] The function to customize assigned values.
13887      * @returns {Object} Returns `object`.
13888      * @example
13889      *
13890      * var object = {};
13891      *
13892      * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13893      * // => { '0': { '1': 'a' } }
13894      */
13895     function updateWith(object, path, updater, customizer) {
13896       customizer = typeof customizer == 'function' ? customizer : undefined;
13897       return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13898     }
13899
13900     /**
13901      * Creates an array of the own enumerable string keyed property values of `object`.
13902      *
13903      * **Note:** Non-object values are coerced to objects.
13904      *
13905      * @static
13906      * @since 0.1.0
13907      * @memberOf _
13908      * @category Object
13909      * @param {Object} object The object to query.
13910      * @returns {Array} Returns the array of property values.
13911      * @example
13912      *
13913      * function Foo() {
13914      *   this.a = 1;
13915      *   this.b = 2;
13916      * }
13917      *
13918      * Foo.prototype.c = 3;
13919      *
13920      * _.values(new Foo);
13921      * // => [1, 2] (iteration order is not guaranteed)
13922      *
13923      * _.values('hi');
13924      * // => ['h', 'i']
13925      */
13926     function values(object) {
13927       return object == null ? [] : baseValues(object, keys(object));
13928     }
13929
13930     /**
13931      * Creates an array of the own and inherited enumerable string keyed property
13932      * values of `object`.
13933      *
13934      * **Note:** Non-object values are coerced to objects.
13935      *
13936      * @static
13937      * @memberOf _
13938      * @since 3.0.0
13939      * @category Object
13940      * @param {Object} object The object to query.
13941      * @returns {Array} Returns the array of property values.
13942      * @example
13943      *
13944      * function Foo() {
13945      *   this.a = 1;
13946      *   this.b = 2;
13947      * }
13948      *
13949      * Foo.prototype.c = 3;
13950      *
13951      * _.valuesIn(new Foo);
13952      * // => [1, 2, 3] (iteration order is not guaranteed)
13953      */
13954     function valuesIn(object) {
13955       return object == null ? [] : baseValues(object, keysIn(object));
13956     }
13957
13958     /*------------------------------------------------------------------------*/
13959
13960     /**
13961      * Clamps `number` within the inclusive `lower` and `upper` bounds.
13962      *
13963      * @static
13964      * @memberOf _
13965      * @since 4.0.0
13966      * @category Number
13967      * @param {number} number The number to clamp.
13968      * @param {number} [lower] The lower bound.
13969      * @param {number} upper The upper bound.
13970      * @returns {number} Returns the clamped number.
13971      * @example
13972      *
13973      * _.clamp(-10, -5, 5);
13974      * // => -5
13975      *
13976      * _.clamp(10, -5, 5);
13977      * // => 5
13978      */
13979     function clamp(number, lower, upper) {
13980       if (upper === undefined) {
13981         upper = lower;
13982         lower = undefined;
13983       }
13984       if (upper !== undefined) {
13985         upper = toNumber(upper);
13986         upper = upper === upper ? upper : 0;
13987       }
13988       if (lower !== undefined) {
13989         lower = toNumber(lower);
13990         lower = lower === lower ? lower : 0;
13991       }
13992       return baseClamp(toNumber(number), lower, upper);
13993     }
13994
13995     /**
13996      * Checks if `n` is between `start` and up to, but not including, `end`. If
13997      * `end` is not specified, it's set to `start` with `start` then set to `0`.
13998      * If `start` is greater than `end` the params are swapped to support
13999      * negative ranges.
14000      *
14001      * @static
14002      * @memberOf _
14003      * @since 3.3.0
14004      * @category Number
14005      * @param {number} number The number to check.
14006      * @param {number} [start=0] The start of the range.
14007      * @param {number} end The end of the range.
14008      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
14009      * @see _.range, _.rangeRight
14010      * @example
14011      *
14012      * _.inRange(3, 2, 4);
14013      * // => true
14014      *
14015      * _.inRange(4, 8);
14016      * // => true
14017      *
14018      * _.inRange(4, 2);
14019      * // => false
14020      *
14021      * _.inRange(2, 2);
14022      * // => false
14023      *
14024      * _.inRange(1.2, 2);
14025      * // => true
14026      *
14027      * _.inRange(5.2, 4);
14028      * // => false
14029      *
14030      * _.inRange(-3, -2, -6);
14031      * // => true
14032      */
14033     function inRange(number, start, end) {
14034       start = toFinite(start);
14035       if (end === undefined) {
14036         end = start;
14037         start = 0;
14038       } else {
14039         end = toFinite(end);
14040       }
14041       number = toNumber(number);
14042       return baseInRange(number, start, end);
14043     }
14044
14045     /**
14046      * Produces a random number between the inclusive `lower` and `upper` bounds.
14047      * If only one argument is provided a number between `0` and the given number
14048      * is returned. If `floating` is `true`, or either `lower` or `upper` are
14049      * floats, a floating-point number is returned instead of an integer.
14050      *
14051      * **Note:** JavaScript follows the IEEE-754 standard for resolving
14052      * floating-point values which can produce unexpected results.
14053      *
14054      * @static
14055      * @memberOf _
14056      * @since 0.7.0
14057      * @category Number
14058      * @param {number} [lower=0] The lower bound.
14059      * @param {number} [upper=1] The upper bound.
14060      * @param {boolean} [floating] Specify returning a floating-point number.
14061      * @returns {number} Returns the random number.
14062      * @example
14063      *
14064      * _.random(0, 5);
14065      * // => an integer between 0 and 5
14066      *
14067      * _.random(5);
14068      * // => also an integer between 0 and 5
14069      *
14070      * _.random(5, true);
14071      * // => a floating-point number between 0 and 5
14072      *
14073      * _.random(1.2, 5.2);
14074      * // => a floating-point number between 1.2 and 5.2
14075      */
14076     function random(lower, upper, floating) {
14077       if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14078         upper = floating = undefined;
14079       }
14080       if (floating === undefined) {
14081         if (typeof upper == 'boolean') {
14082           floating = upper;
14083           upper = undefined;
14084         }
14085         else if (typeof lower == 'boolean') {
14086           floating = lower;
14087           lower = undefined;
14088         }
14089       }
14090       if (lower === undefined && upper === undefined) {
14091         lower = 0;
14092         upper = 1;
14093       }
14094       else {
14095         lower = toFinite(lower);
14096         if (upper === undefined) {
14097           upper = lower;
14098           lower = 0;
14099         } else {
14100           upper = toFinite(upper);
14101         }
14102       }
14103       if (lower > upper) {
14104         var temp = lower;
14105         lower = upper;
14106         upper = temp;
14107       }
14108       if (floating || lower % 1 || upper % 1) {
14109         var rand = nativeRandom();
14110         return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14111       }
14112       return baseRandom(lower, upper);
14113     }
14114
14115     /*------------------------------------------------------------------------*/
14116
14117     /**
14118      * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14119      *
14120      * @static
14121      * @memberOf _
14122      * @since 3.0.0
14123      * @category String
14124      * @param {string} [string=''] The string to convert.
14125      * @returns {string} Returns the camel cased string.
14126      * @example
14127      *
14128      * _.camelCase('Foo Bar');
14129      * // => 'fooBar'
14130      *
14131      * _.camelCase('--foo-bar--');
14132      * // => 'fooBar'
14133      *
14134      * _.camelCase('__FOO_BAR__');
14135      * // => 'fooBar'
14136      */
14137     var camelCase = createCompounder(function(result, word, index) {
14138       word = word.toLowerCase();
14139       return result + (index ? capitalize(word) : word);
14140     });
14141
14142     /**
14143      * Converts the first character of `string` to upper case and the remaining
14144      * to lower case.
14145      *
14146      * @static
14147      * @memberOf _
14148      * @since 3.0.0
14149      * @category String
14150      * @param {string} [string=''] The string to capitalize.
14151      * @returns {string} Returns the capitalized string.
14152      * @example
14153      *
14154      * _.capitalize('FRED');
14155      * // => 'Fred'
14156      */
14157     function capitalize(string) {
14158       return upperFirst(toString(string).toLowerCase());
14159     }
14160
14161     /**
14162      * Deburrs `string` by converting
14163      * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14164      * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14165      * letters to basic Latin letters and removing
14166      * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14167      *
14168      * @static
14169      * @memberOf _
14170      * @since 3.0.0
14171      * @category String
14172      * @param {string} [string=''] The string to deburr.
14173      * @returns {string} Returns the deburred string.
14174      * @example
14175      *
14176      * _.deburr('déjà vu');
14177      * // => 'deja vu'
14178      */
14179     function deburr(string) {
14180       string = toString(string);
14181       return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14182     }
14183
14184     /**
14185      * Checks if `string` ends with the given target string.
14186      *
14187      * @static
14188      * @memberOf _
14189      * @since 3.0.0
14190      * @category String
14191      * @param {string} [string=''] The string to inspect.
14192      * @param {string} [target] The string to search for.
14193      * @param {number} [position=string.length] The position to search up to.
14194      * @returns {boolean} Returns `true` if `string` ends with `target`,
14195      *  else `false`.
14196      * @example
14197      *
14198      * _.endsWith('abc', 'c');
14199      * // => true
14200      *
14201      * _.endsWith('abc', 'b');
14202      * // => false
14203      *
14204      * _.endsWith('abc', 'b', 2);
14205      * // => true
14206      */
14207     function endsWith(string, target, position) {
14208       string = toString(string);
14209       target = baseToString(target);
14210
14211       var length = string.length;
14212       position = position === undefined
14213         ? length
14214         : baseClamp(toInteger(position), 0, length);
14215
14216       var end = position;
14217       position -= target.length;
14218       return position >= 0 && string.slice(position, end) == target;
14219     }
14220
14221     /**
14222      * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14223      * corresponding HTML entities.
14224      *
14225      * **Note:** No other characters are escaped. To escape additional
14226      * characters use a third-party library like [_he_](https://mths.be/he).
14227      *
14228      * Though the ">" character is escaped for symmetry, characters like
14229      * ">" and "/" don't need escaping in HTML and have no special meaning
14230      * unless they're part of a tag or unquoted attribute value. See
14231      * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14232      * (under "semi-related fun fact") for more details.
14233      *
14234      * When working with HTML you should always
14235      * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14236      * XSS vectors.
14237      *
14238      * @static
14239      * @since 0.1.0
14240      * @memberOf _
14241      * @category String
14242      * @param {string} [string=''] The string to escape.
14243      * @returns {string} Returns the escaped string.
14244      * @example
14245      *
14246      * _.escape('fred, barney, & pebbles');
14247      * // => 'fred, barney, &amp; pebbles'
14248      */
14249     function escape(string) {
14250       string = toString(string);
14251       return (string && reHasUnescapedHtml.test(string))
14252         ? string.replace(reUnescapedHtml, escapeHtmlChar)
14253         : string;
14254     }
14255
14256     /**
14257      * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14258      * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14259      *
14260      * @static
14261      * @memberOf _
14262      * @since 3.0.0
14263      * @category String
14264      * @param {string} [string=''] The string to escape.
14265      * @returns {string} Returns the escaped string.
14266      * @example
14267      *
14268      * _.escapeRegExp('[lodash](https://lodash.com/)');
14269      * // => '\[lodash\]\(https://lodash\.com/\)'
14270      */
14271     function escapeRegExp(string) {
14272       string = toString(string);
14273       return (string && reHasRegExpChar.test(string))
14274         ? string.replace(reRegExpChar, '\\$&')
14275         : string;
14276     }
14277
14278     /**
14279      * Converts `string` to
14280      * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14281      *
14282      * @static
14283      * @memberOf _
14284      * @since 3.0.0
14285      * @category String
14286      * @param {string} [string=''] The string to convert.
14287      * @returns {string} Returns the kebab cased string.
14288      * @example
14289      *
14290      * _.kebabCase('Foo Bar');
14291      * // => 'foo-bar'
14292      *
14293      * _.kebabCase('fooBar');
14294      * // => 'foo-bar'
14295      *
14296      * _.kebabCase('__FOO_BAR__');
14297      * // => 'foo-bar'
14298      */
14299     var kebabCase = createCompounder(function(result, word, index) {
14300       return result + (index ? '-' : '') + word.toLowerCase();
14301     });
14302
14303     /**
14304      * Converts `string`, as space separated words, to lower case.
14305      *
14306      * @static
14307      * @memberOf _
14308      * @since 4.0.0
14309      * @category String
14310      * @param {string} [string=''] The string to convert.
14311      * @returns {string} Returns the lower cased string.
14312      * @example
14313      *
14314      * _.lowerCase('--Foo-Bar--');
14315      * // => 'foo bar'
14316      *
14317      * _.lowerCase('fooBar');
14318      * // => 'foo bar'
14319      *
14320      * _.lowerCase('__FOO_BAR__');
14321      * // => 'foo bar'
14322      */
14323     var lowerCase = createCompounder(function(result, word, index) {
14324       return result + (index ? ' ' : '') + word.toLowerCase();
14325     });
14326
14327     /**
14328      * Converts the first character of `string` to lower case.
14329      *
14330      * @static
14331      * @memberOf _
14332      * @since 4.0.0
14333      * @category String
14334      * @param {string} [string=''] The string to convert.
14335      * @returns {string} Returns the converted string.
14336      * @example
14337      *
14338      * _.lowerFirst('Fred');
14339      * // => 'fred'
14340      *
14341      * _.lowerFirst('FRED');
14342      * // => 'fRED'
14343      */
14344     var lowerFirst = createCaseFirst('toLowerCase');
14345
14346     /**
14347      * Pads `string` on the left and right sides if it's shorter than `length`.
14348      * Padding characters are truncated if they can't be evenly divided by `length`.
14349      *
14350      * @static
14351      * @memberOf _
14352      * @since 3.0.0
14353      * @category String
14354      * @param {string} [string=''] The string to pad.
14355      * @param {number} [length=0] The padding length.
14356      * @param {string} [chars=' '] The string used as padding.
14357      * @returns {string} Returns the padded string.
14358      * @example
14359      *
14360      * _.pad('abc', 8);
14361      * // => '  abc   '
14362      *
14363      * _.pad('abc', 8, '_-');
14364      * // => '_-abc_-_'
14365      *
14366      * _.pad('abc', 3);
14367      * // => 'abc'
14368      */
14369     function pad(string, length, chars) {
14370       string = toString(string);
14371       length = toInteger(length);
14372
14373       var strLength = length ? stringSize(string) : 0;
14374       if (!length || strLength >= length) {
14375         return string;
14376       }
14377       var mid = (length - strLength) / 2;
14378       return (
14379         createPadding(nativeFloor(mid), chars) +
14380         string +
14381         createPadding(nativeCeil(mid), chars)
14382       );
14383     }
14384
14385     /**
14386      * Pads `string` on the right side if it's shorter than `length`. Padding
14387      * characters are truncated if they exceed `length`.
14388      *
14389      * @static
14390      * @memberOf _
14391      * @since 4.0.0
14392      * @category String
14393      * @param {string} [string=''] The string to pad.
14394      * @param {number} [length=0] The padding length.
14395      * @param {string} [chars=' '] The string used as padding.
14396      * @returns {string} Returns the padded string.
14397      * @example
14398      *
14399      * _.padEnd('abc', 6);
14400      * // => 'abc   '
14401      *
14402      * _.padEnd('abc', 6, '_-');
14403      * // => 'abc_-_'
14404      *
14405      * _.padEnd('abc', 3);
14406      * // => 'abc'
14407      */
14408     function padEnd(string, length, chars) {
14409       string = toString(string);
14410       length = toInteger(length);
14411
14412       var strLength = length ? stringSize(string) : 0;
14413       return (length && strLength < length)
14414         ? (string + createPadding(length - strLength, chars))
14415         : string;
14416     }
14417
14418     /**
14419      * Pads `string` on the left side if it's shorter than `length`. Padding
14420      * characters are truncated if they exceed `length`.
14421      *
14422      * @static
14423      * @memberOf _
14424      * @since 4.0.0
14425      * @category String
14426      * @param {string} [string=''] The string to pad.
14427      * @param {number} [length=0] The padding length.
14428      * @param {string} [chars=' '] The string used as padding.
14429      * @returns {string} Returns the padded string.
14430      * @example
14431      *
14432      * _.padStart('abc', 6);
14433      * // => '   abc'
14434      *
14435      * _.padStart('abc', 6, '_-');
14436      * // => '_-_abc'
14437      *
14438      * _.padStart('abc', 3);
14439      * // => 'abc'
14440      */
14441     function padStart(string, length, chars) {
14442       string = toString(string);
14443       length = toInteger(length);
14444
14445       var strLength = length ? stringSize(string) : 0;
14446       return (length && strLength < length)
14447         ? (createPadding(length - strLength, chars) + string)
14448         : string;
14449     }
14450
14451     /**
14452      * Converts `string` to an integer of the specified radix. If `radix` is
14453      * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14454      * hexadecimal, in which case a `radix` of `16` is used.
14455      *
14456      * **Note:** This method aligns with the
14457      * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14458      *
14459      * @static
14460      * @memberOf _
14461      * @since 1.1.0
14462      * @category String
14463      * @param {string} string The string to convert.
14464      * @param {number} [radix=10] The radix to interpret `value` by.
14465      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14466      * @returns {number} Returns the converted integer.
14467      * @example
14468      *
14469      * _.parseInt('08');
14470      * // => 8
14471      *
14472      * _.map(['6', '08', '10'], _.parseInt);
14473      * // => [6, 8, 10]
14474      */
14475     function parseInt(string, radix, guard) {
14476       if (guard || radix == null) {
14477         radix = 0;
14478       } else if (radix) {
14479         radix = +radix;
14480       }
14481       return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14482     }
14483
14484     /**
14485      * Repeats the given string `n` times.
14486      *
14487      * @static
14488      * @memberOf _
14489      * @since 3.0.0
14490      * @category String
14491      * @param {string} [string=''] The string to repeat.
14492      * @param {number} [n=1] The number of times to repeat the string.
14493      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14494      * @returns {string} Returns the repeated string.
14495      * @example
14496      *
14497      * _.repeat('*', 3);
14498      * // => '***'
14499      *
14500      * _.repeat('abc', 2);
14501      * // => 'abcabc'
14502      *
14503      * _.repeat('abc', 0);
14504      * // => ''
14505      */
14506     function repeat(string, n, guard) {
14507       if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14508         n = 1;
14509       } else {
14510         n = toInteger(n);
14511       }
14512       return baseRepeat(toString(string), n);
14513     }
14514
14515     /**
14516      * Replaces matches for `pattern` in `string` with `replacement`.
14517      *
14518      * **Note:** This method is based on
14519      * [`String#replace`](https://mdn.io/String/replace).
14520      *
14521      * @static
14522      * @memberOf _
14523      * @since 4.0.0
14524      * @category String
14525      * @param {string} [string=''] The string to modify.
14526      * @param {RegExp|string} pattern The pattern to replace.
14527      * @param {Function|string} replacement The match replacement.
14528      * @returns {string} Returns the modified string.
14529      * @example
14530      *
14531      * _.replace('Hi Fred', 'Fred', 'Barney');
14532      * // => 'Hi Barney'
14533      */
14534     function replace() {
14535       var args = arguments,
14536           string = toString(args[0]);
14537
14538       return args.length < 3 ? string : string.replace(args[1], args[2]);
14539     }
14540
14541     /**
14542      * Converts `string` to
14543      * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14544      *
14545      * @static
14546      * @memberOf _
14547      * @since 3.0.0
14548      * @category String
14549      * @param {string} [string=''] The string to convert.
14550      * @returns {string} Returns the snake cased string.
14551      * @example
14552      *
14553      * _.snakeCase('Foo Bar');
14554      * // => 'foo_bar'
14555      *
14556      * _.snakeCase('fooBar');
14557      * // => 'foo_bar'
14558      *
14559      * _.snakeCase('--FOO-BAR--');
14560      * // => 'foo_bar'
14561      */
14562     var snakeCase = createCompounder(function(result, word, index) {
14563       return result + (index ? '_' : '') + word.toLowerCase();
14564     });
14565
14566     /**
14567      * Splits `string` by `separator`.
14568      *
14569      * **Note:** This method is based on
14570      * [`String#split`](https://mdn.io/String/split).
14571      *
14572      * @static
14573      * @memberOf _
14574      * @since 4.0.0
14575      * @category String
14576      * @param {string} [string=''] The string to split.
14577      * @param {RegExp|string} separator The separator pattern to split by.
14578      * @param {number} [limit] The length to truncate results to.
14579      * @returns {Array} Returns the string segments.
14580      * @example
14581      *
14582      * _.split('a-b-c', '-', 2);
14583      * // => ['a', 'b']
14584      */
14585     function split(string, separator, limit) {
14586       if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14587         separator = limit = undefined;
14588       }
14589       limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14590       if (!limit) {
14591         return [];
14592       }
14593       string = toString(string);
14594       if (string && (
14595             typeof separator == 'string' ||
14596             (separator != null && !isRegExp(separator))
14597           )) {
14598         separator = baseToString(separator);
14599         if (!separator && hasUnicode(string)) {
14600           return castSlice(stringToArray(string), 0, limit);
14601         }
14602       }
14603       return string.split(separator, limit);
14604     }
14605
14606     /**
14607      * Converts `string` to
14608      * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14609      *
14610      * @static
14611      * @memberOf _
14612      * @since 3.1.0
14613      * @category String
14614      * @param {string} [string=''] The string to convert.
14615      * @returns {string} Returns the start cased string.
14616      * @example
14617      *
14618      * _.startCase('--foo-bar--');
14619      * // => 'Foo Bar'
14620      *
14621      * _.startCase('fooBar');
14622      * // => 'Foo Bar'
14623      *
14624      * _.startCase('__FOO_BAR__');
14625      * // => 'FOO BAR'
14626      */
14627     var startCase = createCompounder(function(result, word, index) {
14628       return result + (index ? ' ' : '') + upperFirst(word);
14629     });
14630
14631     /**
14632      * Checks if `string` starts with the given target string.
14633      *
14634      * @static
14635      * @memberOf _
14636      * @since 3.0.0
14637      * @category String
14638      * @param {string} [string=''] The string to inspect.
14639      * @param {string} [target] The string to search for.
14640      * @param {number} [position=0] The position to search from.
14641      * @returns {boolean} Returns `true` if `string` starts with `target`,
14642      *  else `false`.
14643      * @example
14644      *
14645      * _.startsWith('abc', 'a');
14646      * // => true
14647      *
14648      * _.startsWith('abc', 'b');
14649      * // => false
14650      *
14651      * _.startsWith('abc', 'b', 1);
14652      * // => true
14653      */
14654     function startsWith(string, target, position) {
14655       string = toString(string);
14656       position = position == null
14657         ? 0
14658         : baseClamp(toInteger(position), 0, string.length);
14659
14660       target = baseToString(target);
14661       return string.slice(position, position + target.length) == target;
14662     }
14663
14664     /**
14665      * Creates a compiled template function that can interpolate data properties
14666      * in "interpolate" delimiters, HTML-escape interpolated data properties in
14667      * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14668      * properties may be accessed as free variables in the template. If a setting
14669      * object is given, it takes precedence over `_.templateSettings` values.
14670      *
14671      * **Note:** In the development build `_.template` utilizes
14672      * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14673      * for easier debugging.
14674      *
14675      * For more information on precompiling templates see
14676      * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14677      *
14678      * For more information on Chrome extension sandboxes see
14679      * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14680      *
14681      * @static
14682      * @since 0.1.0
14683      * @memberOf _
14684      * @category String
14685      * @param {string} [string=''] The template string.
14686      * @param {Object} [options={}] The options object.
14687      * @param {RegExp} [options.escape=_.templateSettings.escape]
14688      *  The HTML "escape" delimiter.
14689      * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14690      *  The "evaluate" delimiter.
14691      * @param {Object} [options.imports=_.templateSettings.imports]
14692      *  An object to import into the template as free variables.
14693      * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14694      *  The "interpolate" delimiter.
14695      * @param {string} [options.sourceURL='lodash.templateSources[n]']
14696      *  The sourceURL of the compiled template.
14697      * @param {string} [options.variable='obj']
14698      *  The data object variable name.
14699      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14700      * @returns {Function} Returns the compiled template function.
14701      * @example
14702      *
14703      * // Use the "interpolate" delimiter to create a compiled template.
14704      * var compiled = _.template('hello <%= user %>!');
14705      * compiled({ 'user': 'fred' });
14706      * // => 'hello fred!'
14707      *
14708      * // Use the HTML "escape" delimiter to escape data property values.
14709      * var compiled = _.template('<b><%- value %></b>');
14710      * compiled({ 'value': '<script>' });
14711      * // => '<b>&lt;script&gt;</b>'
14712      *
14713      * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14714      * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14715      * compiled({ 'users': ['fred', 'barney'] });
14716      * // => '<li>fred</li><li>barney</li>'
14717      *
14718      * // Use the internal `print` function in "evaluate" delimiters.
14719      * var compiled = _.template('<% print("hello " + user); %>!');
14720      * compiled({ 'user': 'barney' });
14721      * // => 'hello barney!'
14722      *
14723      * // Use the ES template literal delimiter as an "interpolate" delimiter.
14724      * // Disable support by replacing the "interpolate" delimiter.
14725      * var compiled = _.template('hello ${ user }!');
14726      * compiled({ 'user': 'pebbles' });
14727      * // => 'hello pebbles!'
14728      *
14729      * // Use backslashes to treat delimiters as plain text.
14730      * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14731      * compiled({ 'value': 'ignored' });
14732      * // => '<%- value %>'
14733      *
14734      * // Use the `imports` option to import `jQuery` as `jq`.
14735      * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14736      * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14737      * compiled({ 'users': ['fred', 'barney'] });
14738      * // => '<li>fred</li><li>barney</li>'
14739      *
14740      * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14741      * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14742      * compiled(data);
14743      * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14744      *
14745      * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14746      * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14747      * compiled.source;
14748      * // => function(data) {
14749      * //   var __t, __p = '';
14750      * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14751      * //   return __p;
14752      * // }
14753      *
14754      * // Use custom template delimiters.
14755      * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14756      * var compiled = _.template('hello {{ user }}!');
14757      * compiled({ 'user': 'mustache' });
14758      * // => 'hello mustache!'
14759      *
14760      * // Use the `source` property to inline compiled templates for meaningful
14761      * // line numbers in error messages and stack traces.
14762      * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14763      *   var JST = {\
14764      *     "main": ' + _.template(mainText).source + '\
14765      *   };\
14766      * ');
14767      */
14768     function template(string, options, guard) {
14769       // Based on John Resig's `tmpl` implementation
14770       // (http://ejohn.org/blog/javascript-micro-templating/)
14771       // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14772       var settings = lodash.templateSettings;
14773
14774       if (guard && isIterateeCall(string, options, guard)) {
14775         options = undefined;
14776       }
14777       string = toString(string);
14778       options = assignInWith({}, options, settings, customDefaultsAssignIn);
14779
14780       var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
14781           importsKeys = keys(imports),
14782           importsValues = baseValues(imports, importsKeys);
14783
14784       var isEscaping,
14785           isEvaluating,
14786           index = 0,
14787           interpolate = options.interpolate || reNoMatch,
14788           source = "__p += '";
14789
14790       // Compile the regexp to match each delimiter.
14791       var reDelimiters = RegExp(
14792         (options.escape || reNoMatch).source + '|' +
14793         interpolate.source + '|' +
14794         (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14795         (options.evaluate || reNoMatch).source + '|$'
14796       , 'g');
14797
14798       // Use a sourceURL for easier debugging.
14799       var sourceURL = '//# sourceURL=' +
14800         ('sourceURL' in options
14801           ? options.sourceURL
14802           : ('lodash.templateSources[' + (++templateCounter) + ']')
14803         ) + '\n';
14804
14805       string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14806         interpolateValue || (interpolateValue = esTemplateValue);
14807
14808         // Escape characters that can't be included in string literals.
14809         source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14810
14811         // Replace delimiters with snippets.
14812         if (escapeValue) {
14813           isEscaping = true;
14814           source += "' +\n__e(" + escapeValue + ") +\n'";
14815         }
14816         if (evaluateValue) {
14817           isEvaluating = true;
14818           source += "';\n" + evaluateValue + ";\n__p += '";
14819         }
14820         if (interpolateValue) {
14821           source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14822         }
14823         index = offset + match.length;
14824
14825         // The JS engine embedded in Adobe products needs `match` returned in
14826         // order to produce the correct `offset` value.
14827         return match;
14828       });
14829
14830       source += "';\n";
14831
14832       // If `variable` is not specified wrap a with-statement around the generated
14833       // code to add the data object to the top of the scope chain.
14834       var variable = options.variable;
14835       if (!variable) {
14836         source = 'with (obj) {\n' + source + '\n}\n';
14837       }
14838       // Cleanup code by stripping empty strings.
14839       source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14840         .replace(reEmptyStringMiddle, '$1')
14841         .replace(reEmptyStringTrailing, '$1;');
14842
14843       // Frame code as the function body.
14844       source = 'function(' + (variable || 'obj') + ') {\n' +
14845         (variable
14846           ? ''
14847           : 'obj || (obj = {});\n'
14848         ) +
14849         "var __t, __p = ''" +
14850         (isEscaping
14851            ? ', __e = _.escape'
14852            : ''
14853         ) +
14854         (isEvaluating
14855           ? ', __j = Array.prototype.join;\n' +
14856             "function print() { __p += __j.call(arguments, '') }\n"
14857           : ';\n'
14858         ) +
14859         source +
14860         'return __p\n}';
14861
14862       var result = attempt(function() {
14863         return Function(importsKeys, sourceURL + 'return ' + source)
14864           .apply(undefined, importsValues);
14865       });
14866
14867       // Provide the compiled function's source by its `toString` method or
14868       // the `source` property as a convenience for inlining compiled templates.
14869       result.source = source;
14870       if (isError(result)) {
14871         throw result;
14872       }
14873       return result;
14874     }
14875
14876     /**
14877      * Converts `string`, as a whole, to lower case just like
14878      * [String#toLowerCase](https://mdn.io/toLowerCase).
14879      *
14880      * @static
14881      * @memberOf _
14882      * @since 4.0.0
14883      * @category String
14884      * @param {string} [string=''] The string to convert.
14885      * @returns {string} Returns the lower cased string.
14886      * @example
14887      *
14888      * _.toLower('--Foo-Bar--');
14889      * // => '--foo-bar--'
14890      *
14891      * _.toLower('fooBar');
14892      * // => 'foobar'
14893      *
14894      * _.toLower('__FOO_BAR__');
14895      * // => '__foo_bar__'
14896      */
14897     function toLower(value) {
14898       return toString(value).toLowerCase();
14899     }
14900
14901     /**
14902      * Converts `string`, as a whole, to upper case just like
14903      * [String#toUpperCase](https://mdn.io/toUpperCase).
14904      *
14905      * @static
14906      * @memberOf _
14907      * @since 4.0.0
14908      * @category String
14909      * @param {string} [string=''] The string to convert.
14910      * @returns {string} Returns the upper cased string.
14911      * @example
14912      *
14913      * _.toUpper('--foo-bar--');
14914      * // => '--FOO-BAR--'
14915      *
14916      * _.toUpper('fooBar');
14917      * // => 'FOOBAR'
14918      *
14919      * _.toUpper('__foo_bar__');
14920      * // => '__FOO_BAR__'
14921      */
14922     function toUpper(value) {
14923       return toString(value).toUpperCase();
14924     }
14925
14926     /**
14927      * Removes leading and trailing whitespace or specified characters from `string`.
14928      *
14929      * @static
14930      * @memberOf _
14931      * @since 3.0.0
14932      * @category String
14933      * @param {string} [string=''] The string to trim.
14934      * @param {string} [chars=whitespace] The characters to trim.
14935      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14936      * @returns {string} Returns the trimmed string.
14937      * @example
14938      *
14939      * _.trim('  abc  ');
14940      * // => 'abc'
14941      *
14942      * _.trim('-_-abc-_-', '_-');
14943      * // => 'abc'
14944      *
14945      * _.map(['  foo  ', '  bar  '], _.trim);
14946      * // => ['foo', 'bar']
14947      */
14948     function trim(string, chars, guard) {
14949       string = toString(string);
14950       if (string && (guard || chars === undefined)) {
14951         return string.replace(reTrim, '');
14952       }
14953       if (!string || !(chars = baseToString(chars))) {
14954         return string;
14955       }
14956       var strSymbols = stringToArray(string),
14957           chrSymbols = stringToArray(chars),
14958           start = charsStartIndex(strSymbols, chrSymbols),
14959           end = charsEndIndex(strSymbols, chrSymbols) + 1;
14960
14961       return castSlice(strSymbols, start, end).join('');
14962     }
14963
14964     /**
14965      * Removes trailing whitespace or specified characters from `string`.
14966      *
14967      * @static
14968      * @memberOf _
14969      * @since 4.0.0
14970      * @category String
14971      * @param {string} [string=''] The string to trim.
14972      * @param {string} [chars=whitespace] The characters to trim.
14973      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14974      * @returns {string} Returns the trimmed string.
14975      * @example
14976      *
14977      * _.trimEnd('  abc  ');
14978      * // => '  abc'
14979      *
14980      * _.trimEnd('-_-abc-_-', '_-');
14981      * // => '-_-abc'
14982      */
14983     function trimEnd(string, chars, guard) {
14984       string = toString(string);
14985       if (string && (guard || chars === undefined)) {
14986         return string.replace(reTrimEnd, '');
14987       }
14988       if (!string || !(chars = baseToString(chars))) {
14989         return string;
14990       }
14991       var strSymbols = stringToArray(string),
14992           end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14993
14994       return castSlice(strSymbols, 0, end).join('');
14995     }
14996
14997     /**
14998      * Removes leading whitespace or specified characters from `string`.
14999      *
15000      * @static
15001      * @memberOf _
15002      * @since 4.0.0
15003      * @category String
15004      * @param {string} [string=''] The string to trim.
15005      * @param {string} [chars=whitespace] The characters to trim.
15006      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15007      * @returns {string} Returns the trimmed string.
15008      * @example
15009      *
15010      * _.trimStart('  abc  ');
15011      * // => 'abc  '
15012      *
15013      * _.trimStart('-_-abc-_-', '_-');
15014      * // => 'abc-_-'
15015      */
15016     function trimStart(string, chars, guard) {
15017       string = toString(string);
15018       if (string && (guard || chars === undefined)) {
15019         return string.replace(reTrimStart, '');
15020       }
15021       if (!string || !(chars = baseToString(chars))) {
15022         return string;
15023       }
15024       var strSymbols = stringToArray(string),
15025           start = charsStartIndex(strSymbols, stringToArray(chars));
15026
15027       return castSlice(strSymbols, start).join('');
15028     }
15029
15030     /**
15031      * Truncates `string` if it's longer than the given maximum string length.
15032      * The last characters of the truncated string are replaced with the omission
15033      * string which defaults to "...".
15034      *
15035      * @static
15036      * @memberOf _
15037      * @since 4.0.0
15038      * @category String
15039      * @param {string} [string=''] The string to truncate.
15040      * @param {Object} [options={}] The options object.
15041      * @param {number} [options.length=30] The maximum string length.
15042      * @param {string} [options.omission='...'] The string to indicate text is omitted.
15043      * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15044      * @returns {string} Returns the truncated string.
15045      * @example
15046      *
15047      * _.truncate('hi-diddly-ho there, neighborino');
15048      * // => 'hi-diddly-ho there, neighbo...'
15049      *
15050      * _.truncate('hi-diddly-ho there, neighborino', {
15051      *   'length': 24,
15052      *   'separator': ' '
15053      * });
15054      * // => 'hi-diddly-ho there,...'
15055      *
15056      * _.truncate('hi-diddly-ho there, neighborino', {
15057      *   'length': 24,
15058      *   'separator': /,? +/
15059      * });
15060      * // => 'hi-diddly-ho there...'
15061      *
15062      * _.truncate('hi-diddly-ho there, neighborino', {
15063      *   'omission': ' [...]'
15064      * });
15065      * // => 'hi-diddly-ho there, neig [...]'
15066      */
15067     function truncate(string, options) {
15068       var length = DEFAULT_TRUNC_LENGTH,
15069           omission = DEFAULT_TRUNC_OMISSION;
15070
15071       if (isObject(options)) {
15072         var separator = 'separator' in options ? options.separator : separator;
15073         length = 'length' in options ? toInteger(options.length) : length;
15074         omission = 'omission' in options ? baseToString(options.omission) : omission;
15075       }
15076       string = toString(string);
15077
15078       var strLength = string.length;
15079       if (hasUnicode(string)) {
15080         var strSymbols = stringToArray(string);
15081         strLength = strSymbols.length;
15082       }
15083       if (length >= strLength) {
15084         return string;
15085       }
15086       var end = length - stringSize(omission);
15087       if (end < 1) {
15088         return omission;
15089       }
15090       var result = strSymbols
15091         ? castSlice(strSymbols, 0, end).join('')
15092         : string.slice(0, end);
15093
15094       if (separator === undefined) {
15095         return result + omission;
15096       }
15097       if (strSymbols) {
15098         end += (result.length - end);
15099       }
15100       if (isRegExp(separator)) {
15101         if (string.slice(end).search(separator)) {
15102           var match,
15103               substring = result;
15104
15105           if (!separator.global) {
15106             separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15107           }
15108           separator.lastIndex = 0;
15109           while ((match = separator.exec(substring))) {
15110             var newEnd = match.index;
15111           }
15112           result = result.slice(0, newEnd === undefined ? end : newEnd);
15113         }
15114       } else if (string.indexOf(baseToString(separator), end) != end) {
15115         var index = result.lastIndexOf(separator);
15116         if (index > -1) {
15117           result = result.slice(0, index);
15118         }
15119       }
15120       return result + omission;
15121     }
15122
15123     /**
15124      * The inverse of `_.escape`; this method converts the HTML entities
15125      * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
15126      * their corresponding characters.
15127      *
15128      * **Note:** No other HTML entities are unescaped. To unescape additional
15129      * HTML entities use a third-party library like [_he_](https://mths.be/he).
15130      *
15131      * @static
15132      * @memberOf _
15133      * @since 0.6.0
15134      * @category String
15135      * @param {string} [string=''] The string to unescape.
15136      * @returns {string} Returns the unescaped string.
15137      * @example
15138      *
15139      * _.unescape('fred, barney, &amp; pebbles');
15140      * // => 'fred, barney, & pebbles'
15141      */
15142     function unescape(string) {
15143       string = toString(string);
15144       return (string && reHasEscapedHtml.test(string))
15145         ? string.replace(reEscapedHtml, unescapeHtmlChar)
15146         : string;
15147     }
15148
15149     /**
15150      * Converts `string`, as space separated words, to upper case.
15151      *
15152      * @static
15153      * @memberOf _
15154      * @since 4.0.0
15155      * @category String
15156      * @param {string} [string=''] The string to convert.
15157      * @returns {string} Returns the upper cased string.
15158      * @example
15159      *
15160      * _.upperCase('--foo-bar');
15161      * // => 'FOO BAR'
15162      *
15163      * _.upperCase('fooBar');
15164      * // => 'FOO BAR'
15165      *
15166      * _.upperCase('__foo_bar__');
15167      * // => 'FOO BAR'
15168      */
15169     var upperCase = createCompounder(function(result, word, index) {
15170       return result + (index ? ' ' : '') + word.toUpperCase();
15171     });
15172
15173     /**
15174      * Converts the first character of `string` to upper case.
15175      *
15176      * @static
15177      * @memberOf _
15178      * @since 4.0.0
15179      * @category String
15180      * @param {string} [string=''] The string to convert.
15181      * @returns {string} Returns the converted string.
15182      * @example
15183      *
15184      * _.upperFirst('fred');
15185      * // => 'Fred'
15186      *
15187      * _.upperFirst('FRED');
15188      * // => 'FRED'
15189      */
15190     var upperFirst = createCaseFirst('toUpperCase');
15191
15192     /**
15193      * Splits `string` into an array of its words.
15194      *
15195      * @static
15196      * @memberOf _
15197      * @since 3.0.0
15198      * @category String
15199      * @param {string} [string=''] The string to inspect.
15200      * @param {RegExp|string} [pattern] The pattern to match words.
15201      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15202      * @returns {Array} Returns the words of `string`.
15203      * @example
15204      *
15205      * _.words('fred, barney, & pebbles');
15206      * // => ['fred', 'barney', 'pebbles']
15207      *
15208      * _.words('fred, barney, & pebbles', /[^, ]+/g);
15209      * // => ['fred', 'barney', '&', 'pebbles']
15210      */
15211     function words(string, pattern, guard) {
15212       string = toString(string);
15213       pattern = guard ? undefined : pattern;
15214
15215       if (pattern === undefined) {
15216         return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15217       }
15218       return string.match(pattern) || [];
15219     }
15220
15221     /*------------------------------------------------------------------------*/
15222
15223     /**
15224      * Attempts to invoke `func`, returning either the result or the caught error
15225      * object. Any additional arguments are provided to `func` when it's invoked.
15226      *
15227      * @static
15228      * @memberOf _
15229      * @since 3.0.0
15230      * @category Util
15231      * @param {Function} func The function to attempt.
15232      * @param {...*} [args] The arguments to invoke `func` with.
15233      * @returns {*} Returns the `func` result or error object.
15234      * @example
15235      *
15236      * // Avoid throwing errors for invalid selectors.
15237      * var elements = _.attempt(function(selector) {
15238      *   return document.querySelectorAll(selector);
15239      * }, '>_>');
15240      *
15241      * if (_.isError(elements)) {
15242      *   elements = [];
15243      * }
15244      */
15245     var attempt = baseRest(function(func, args) {
15246       try {
15247         return apply(func, undefined, args);
15248       } catch (e) {
15249         return isError(e) ? e : new Error(e);
15250       }
15251     });
15252
15253     /**
15254      * Binds methods of an object to the object itself, overwriting the existing
15255      * method.
15256      *
15257      * **Note:** This method doesn't set the "length" property of bound functions.
15258      *
15259      * @static
15260      * @since 0.1.0
15261      * @memberOf _
15262      * @category Util
15263      * @param {Object} object The object to bind and assign the bound methods to.
15264      * @param {...(string|string[])} methodNames The object method names to bind.
15265      * @returns {Object} Returns `object`.
15266      * @example
15267      *
15268      * var view = {
15269      *   'label': 'docs',
15270      *   'click': function() {
15271      *     console.log('clicked ' + this.label);
15272      *   }
15273      * };
15274      *
15275      * _.bindAll(view, ['click']);
15276      * jQuery(element).on('click', view.click);
15277      * // => Logs 'clicked docs' when clicked.
15278      */
15279     var bindAll = flatRest(function(object, methodNames) {
15280       arrayEach(methodNames, function(key) {
15281         key = toKey(key);
15282         baseAssignValue(object, key, bind(object[key], object));
15283       });
15284       return object;
15285     });
15286
15287     /**
15288      * Creates a function that iterates over `pairs` and invokes the corresponding
15289      * function of the first predicate to return truthy. The predicate-function
15290      * pairs are invoked with the `this` binding and arguments of the created
15291      * function.
15292      *
15293      * @static
15294      * @memberOf _
15295      * @since 4.0.0
15296      * @category Util
15297      * @param {Array} pairs The predicate-function pairs.
15298      * @returns {Function} Returns the new composite function.
15299      * @example
15300      *
15301      * var func = _.cond([
15302      *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
15303      *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15304      *   [_.stubTrue,                      _.constant('no match')]
15305      * ]);
15306      *
15307      * func({ 'a': 1, 'b': 2 });
15308      * // => 'matches A'
15309      *
15310      * func({ 'a': 0, 'b': 1 });
15311      * // => 'matches B'
15312      *
15313      * func({ 'a': '1', 'b': '2' });
15314      * // => 'no match'
15315      */
15316     function cond(pairs) {
15317       var length = pairs == null ? 0 : pairs.length,
15318           toIteratee = getIteratee();
15319
15320       pairs = !length ? [] : arrayMap(pairs, function(pair) {
15321         if (typeof pair[1] != 'function') {
15322           throw new TypeError(FUNC_ERROR_TEXT);
15323         }
15324         return [toIteratee(pair[0]), pair[1]];
15325       });
15326
15327       return baseRest(function(args) {
15328         var index = -1;
15329         while (++index < length) {
15330           var pair = pairs[index];
15331           if (apply(pair[0], this, args)) {
15332             return apply(pair[1], this, args);
15333           }
15334         }
15335       });
15336     }
15337
15338     /**
15339      * Creates a function that invokes the predicate properties of `source` with
15340      * the corresponding property values of a given object, returning `true` if
15341      * all predicates return truthy, else `false`.
15342      *
15343      * **Note:** The created function is equivalent to `_.conformsTo` with
15344      * `source` partially applied.
15345      *
15346      * @static
15347      * @memberOf _
15348      * @since 4.0.0
15349      * @category Util
15350      * @param {Object} source The object of property predicates to conform to.
15351      * @returns {Function} Returns the new spec function.
15352      * @example
15353      *
15354      * var objects = [
15355      *   { 'a': 2, 'b': 1 },
15356      *   { 'a': 1, 'b': 2 }
15357      * ];
15358      *
15359      * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15360      * // => [{ 'a': 1, 'b': 2 }]
15361      */
15362     function conforms(source) {
15363       return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15364     }
15365
15366     /**
15367      * Creates a function that returns `value`.
15368      *
15369      * @static
15370      * @memberOf _
15371      * @since 2.4.0
15372      * @category Util
15373      * @param {*} value The value to return from the new function.
15374      * @returns {Function} Returns the new constant function.
15375      * @example
15376      *
15377      * var objects = _.times(2, _.constant({ 'a': 1 }));
15378      *
15379      * console.log(objects);
15380      * // => [{ 'a': 1 }, { 'a': 1 }]
15381      *
15382      * console.log(objects[0] === objects[1]);
15383      * // => true
15384      */
15385     function constant(value) {
15386       return function() {
15387         return value;
15388       };
15389     }
15390
15391     /**
15392      * Checks `value` to determine whether a default value should be returned in
15393      * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15394      * or `undefined`.
15395      *
15396      * @static
15397      * @memberOf _
15398      * @since 4.14.0
15399      * @category Util
15400      * @param {*} value The value to check.
15401      * @param {*} defaultValue The default value.
15402      * @returns {*} Returns the resolved value.
15403      * @example
15404      *
15405      * _.defaultTo(1, 10);
15406      * // => 1
15407      *
15408      * _.defaultTo(undefined, 10);
15409      * // => 10
15410      */
15411     function defaultTo(value, defaultValue) {
15412       return (value == null || value !== value) ? defaultValue : value;
15413     }
15414
15415     /**
15416      * Creates a function that returns the result of invoking the given functions
15417      * with the `this` binding of the created function, where each successive
15418      * invocation is supplied the return value of the previous.
15419      *
15420      * @static
15421      * @memberOf _
15422      * @since 3.0.0
15423      * @category Util
15424      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15425      * @returns {Function} Returns the new composite function.
15426      * @see _.flowRight
15427      * @example
15428      *
15429      * function square(n) {
15430      *   return n * n;
15431      * }
15432      *
15433      * var addSquare = _.flow([_.add, square]);
15434      * addSquare(1, 2);
15435      * // => 9
15436      */
15437     var flow = createFlow();
15438
15439     /**
15440      * This method is like `_.flow` except that it creates a function that
15441      * invokes the given functions from right to left.
15442      *
15443      * @static
15444      * @since 3.0.0
15445      * @memberOf _
15446      * @category Util
15447      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15448      * @returns {Function} Returns the new composite function.
15449      * @see _.flow
15450      * @example
15451      *
15452      * function square(n) {
15453      *   return n * n;
15454      * }
15455      *
15456      * var addSquare = _.flowRight([square, _.add]);
15457      * addSquare(1, 2);
15458      * // => 9
15459      */
15460     var flowRight = createFlow(true);
15461
15462     /**
15463      * This method returns the first argument it receives.
15464      *
15465      * @static
15466      * @since 0.1.0
15467      * @memberOf _
15468      * @category Util
15469      * @param {*} value Any value.
15470      * @returns {*} Returns `value`.
15471      * @example
15472      *
15473      * var object = { 'a': 1 };
15474      *
15475      * console.log(_.identity(object) === object);
15476      * // => true
15477      */
15478     function identity(value) {
15479       return value;
15480     }
15481
15482     /**
15483      * Creates a function that invokes `func` with the arguments of the created
15484      * function. If `func` is a property name, the created function returns the
15485      * property value for a given element. If `func` is an array or object, the
15486      * created function returns `true` for elements that contain the equivalent
15487      * source properties, otherwise it returns `false`.
15488      *
15489      * @static
15490      * @since 4.0.0
15491      * @memberOf _
15492      * @category Util
15493      * @param {*} [func=_.identity] The value to convert to a callback.
15494      * @returns {Function} Returns the callback.
15495      * @example
15496      *
15497      * var users = [
15498      *   { 'user': 'barney', 'age': 36, 'active': true },
15499      *   { 'user': 'fred',   'age': 40, 'active': false }
15500      * ];
15501      *
15502      * // The `_.matches` iteratee shorthand.
15503      * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15504      * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15505      *
15506      * // The `_.matchesProperty` iteratee shorthand.
15507      * _.filter(users, _.iteratee(['user', 'fred']));
15508      * // => [{ 'user': 'fred', 'age': 40 }]
15509      *
15510      * // The `_.property` iteratee shorthand.
15511      * _.map(users, _.iteratee('user'));
15512      * // => ['barney', 'fred']
15513      *
15514      * // Create custom iteratee shorthands.
15515      * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15516      *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
15517      *     return func.test(string);
15518      *   };
15519      * });
15520      *
15521      * _.filter(['abc', 'def'], /ef/);
15522      * // => ['def']
15523      */
15524     function iteratee(func) {
15525       return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15526     }
15527
15528     /**
15529      * Creates a function that performs a partial deep comparison between a given
15530      * object and `source`, returning `true` if the given object has equivalent
15531      * property values, else `false`.
15532      *
15533      * **Note:** The created function is equivalent to `_.isMatch` with `source`
15534      * partially applied.
15535      *
15536      * Partial comparisons will match empty array and empty object `source`
15537      * values against any array or object value, respectively. See `_.isEqual`
15538      * for a list of supported value comparisons.
15539      *
15540      * @static
15541      * @memberOf _
15542      * @since 3.0.0
15543      * @category Util
15544      * @param {Object} source The object of property values to match.
15545      * @returns {Function} Returns the new spec function.
15546      * @example
15547      *
15548      * var objects = [
15549      *   { 'a': 1, 'b': 2, 'c': 3 },
15550      *   { 'a': 4, 'b': 5, 'c': 6 }
15551      * ];
15552      *
15553      * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15554      * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15555      */
15556     function matches(source) {
15557       return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15558     }
15559
15560     /**
15561      * Creates a function that performs a partial deep comparison between the
15562      * value at `path` of a given object to `srcValue`, returning `true` if the
15563      * object value is equivalent, else `false`.
15564      *
15565      * **Note:** Partial comparisons will match empty array and empty object
15566      * `srcValue` values against any array or object value, respectively. See
15567      * `_.isEqual` for a list of supported value comparisons.
15568      *
15569      * @static
15570      * @memberOf _
15571      * @since 3.2.0
15572      * @category Util
15573      * @param {Array|string} path The path of the property to get.
15574      * @param {*} srcValue The value to match.
15575      * @returns {Function} Returns the new spec function.
15576      * @example
15577      *
15578      * var objects = [
15579      *   { 'a': 1, 'b': 2, 'c': 3 },
15580      *   { 'a': 4, 'b': 5, 'c': 6 }
15581      * ];
15582      *
15583      * _.find(objects, _.matchesProperty('a', 4));
15584      * // => { 'a': 4, 'b': 5, 'c': 6 }
15585      */
15586     function matchesProperty(path, srcValue) {
15587       return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15588     }
15589
15590     /**
15591      * Creates a function that invokes the method at `path` of a given object.
15592      * Any additional arguments are provided to the invoked method.
15593      *
15594      * @static
15595      * @memberOf _
15596      * @since 3.7.0
15597      * @category Util
15598      * @param {Array|string} path The path of the method to invoke.
15599      * @param {...*} [args] The arguments to invoke the method with.
15600      * @returns {Function} Returns the new invoker function.
15601      * @example
15602      *
15603      * var objects = [
15604      *   { 'a': { 'b': _.constant(2) } },
15605      *   { 'a': { 'b': _.constant(1) } }
15606      * ];
15607      *
15608      * _.map(objects, _.method('a.b'));
15609      * // => [2, 1]
15610      *
15611      * _.map(objects, _.method(['a', 'b']));
15612      * // => [2, 1]
15613      */
15614     var method = baseRest(function(path, args) {
15615       return function(object) {
15616         return baseInvoke(object, path, args);
15617       };
15618     });
15619
15620     /**
15621      * The opposite of `_.method`; this method creates a function that invokes
15622      * the method at a given path of `object`. Any additional arguments are
15623      * provided to the invoked method.
15624      *
15625      * @static
15626      * @memberOf _
15627      * @since 3.7.0
15628      * @category Util
15629      * @param {Object} object The object to query.
15630      * @param {...*} [args] The arguments to invoke the method with.
15631      * @returns {Function} Returns the new invoker function.
15632      * @example
15633      *
15634      * var array = _.times(3, _.constant),
15635      *     object = { 'a': array, 'b': array, 'c': array };
15636      *
15637      * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15638      * // => [2, 0]
15639      *
15640      * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15641      * // => [2, 0]
15642      */
15643     var methodOf = baseRest(function(object, args) {
15644       return function(path) {
15645         return baseInvoke(object, path, args);
15646       };
15647     });
15648
15649     /**
15650      * Adds all own enumerable string keyed function properties of a source
15651      * object to the destination object. If `object` is a function, then methods
15652      * are added to its prototype as well.
15653      *
15654      * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15655      * avoid conflicts caused by modifying the original.
15656      *
15657      * @static
15658      * @since 0.1.0
15659      * @memberOf _
15660      * @category Util
15661      * @param {Function|Object} [object=lodash] The destination object.
15662      * @param {Object} source The object of functions to add.
15663      * @param {Object} [options={}] The options object.
15664      * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15665      * @returns {Function|Object} Returns `object`.
15666      * @example
15667      *
15668      * function vowels(string) {
15669      *   return _.filter(string, function(v) {
15670      *     return /[aeiou]/i.test(v);
15671      *   });
15672      * }
15673      *
15674      * _.mixin({ 'vowels': vowels });
15675      * _.vowels('fred');
15676      * // => ['e']
15677      *
15678      * _('fred').vowels().value();
15679      * // => ['e']
15680      *
15681      * _.mixin({ 'vowels': vowels }, { 'chain': false });
15682      * _('fred').vowels();
15683      * // => ['e']
15684      */
15685     function mixin(object, source, options) {
15686       var props = keys(source),
15687           methodNames = baseFunctions(source, props);
15688
15689       if (options == null &&
15690           !(isObject(source) && (methodNames.length || !props.length))) {
15691         options = source;
15692         source = object;
15693         object = this;
15694         methodNames = baseFunctions(source, keys(source));
15695       }
15696       var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15697           isFunc = isFunction(object);
15698
15699       arrayEach(methodNames, function(methodName) {
15700         var func = source[methodName];
15701         object[methodName] = func;
15702         if (isFunc) {
15703           object.prototype[methodName] = function() {
15704             var chainAll = this.__chain__;
15705             if (chain || chainAll) {
15706               var result = object(this.__wrapped__),
15707                   actions = result.__actions__ = copyArray(this.__actions__);
15708
15709               actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15710               result.__chain__ = chainAll;
15711               return result;
15712             }
15713             return func.apply(object, arrayPush([this.value()], arguments));
15714           };
15715         }
15716       });
15717
15718       return object;
15719     }
15720
15721     /**
15722      * Reverts the `_` variable to its previous value and returns a reference to
15723      * the `lodash` function.
15724      *
15725      * @static
15726      * @since 0.1.0
15727      * @memberOf _
15728      * @category Util
15729      * @returns {Function} Returns the `lodash` function.
15730      * @example
15731      *
15732      * var lodash = _.noConflict();
15733      */
15734     function noConflict() {
15735       if (root._ === this) {
15736         root._ = oldDash;
15737       }
15738       return this;
15739     }
15740
15741     /**
15742      * This method returns `undefined`.
15743      *
15744      * @static
15745      * @memberOf _
15746      * @since 2.3.0
15747      * @category Util
15748      * @example
15749      *
15750      * _.times(2, _.noop);
15751      * // => [undefined, undefined]
15752      */
15753     function noop() {
15754       // No operation performed.
15755     }
15756
15757     /**
15758      * Creates a function that gets the argument at index `n`. If `n` is negative,
15759      * the nth argument from the end is returned.
15760      *
15761      * @static
15762      * @memberOf _
15763      * @since 4.0.0
15764      * @category Util
15765      * @param {number} [n=0] The index of the argument to return.
15766      * @returns {Function} Returns the new pass-thru function.
15767      * @example
15768      *
15769      * var func = _.nthArg(1);
15770      * func('a', 'b', 'c', 'd');
15771      * // => 'b'
15772      *
15773      * var func = _.nthArg(-2);
15774      * func('a', 'b', 'c', 'd');
15775      * // => 'c'
15776      */
15777     function nthArg(n) {
15778       n = toInteger(n);
15779       return baseRest(function(args) {
15780         return baseNth(args, n);
15781       });
15782     }
15783
15784     /**
15785      * Creates a function that invokes `iteratees` with the arguments it receives
15786      * and returns their results.
15787      *
15788      * @static
15789      * @memberOf _
15790      * @since 4.0.0
15791      * @category Util
15792      * @param {...(Function|Function[])} [iteratees=[_.identity]]
15793      *  The iteratees to invoke.
15794      * @returns {Function} Returns the new function.
15795      * @example
15796      *
15797      * var func = _.over([Math.max, Math.min]);
15798      *
15799      * func(1, 2, 3, 4);
15800      * // => [4, 1]
15801      */
15802     var over = createOver(arrayMap);
15803
15804     /**
15805      * Creates a function that checks if **all** of the `predicates` return
15806      * truthy when invoked with the arguments it receives.
15807      *
15808      * @static
15809      * @memberOf _
15810      * @since 4.0.0
15811      * @category Util
15812      * @param {...(Function|Function[])} [predicates=[_.identity]]
15813      *  The predicates to check.
15814      * @returns {Function} Returns the new function.
15815      * @example
15816      *
15817      * var func = _.overEvery([Boolean, isFinite]);
15818      *
15819      * func('1');
15820      * // => true
15821      *
15822      * func(null);
15823      * // => false
15824      *
15825      * func(NaN);
15826      * // => false
15827      */
15828     var overEvery = createOver(arrayEvery);
15829
15830     /**
15831      * Creates a function that checks if **any** of the `predicates` return
15832      * truthy when invoked with the arguments it receives.
15833      *
15834      * @static
15835      * @memberOf _
15836      * @since 4.0.0
15837      * @category Util
15838      * @param {...(Function|Function[])} [predicates=[_.identity]]
15839      *  The predicates to check.
15840      * @returns {Function} Returns the new function.
15841      * @example
15842      *
15843      * var func = _.overSome([Boolean, isFinite]);
15844      *
15845      * func('1');
15846      * // => true
15847      *
15848      * func(null);
15849      * // => true
15850      *
15851      * func(NaN);
15852      * // => false
15853      */
15854     var overSome = createOver(arraySome);
15855
15856     /**
15857      * Creates a function that returns the value at `path` of a given object.
15858      *
15859      * @static
15860      * @memberOf _
15861      * @since 2.4.0
15862      * @category Util
15863      * @param {Array|string} path The path of the property to get.
15864      * @returns {Function} Returns the new accessor function.
15865      * @example
15866      *
15867      * var objects = [
15868      *   { 'a': { 'b': 2 } },
15869      *   { 'a': { 'b': 1 } }
15870      * ];
15871      *
15872      * _.map(objects, _.property('a.b'));
15873      * // => [2, 1]
15874      *
15875      * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15876      * // => [1, 2]
15877      */
15878     function property(path) {
15879       return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15880     }
15881
15882     /**
15883      * The opposite of `_.property`; this method creates a function that returns
15884      * the value at a given path of `object`.
15885      *
15886      * @static
15887      * @memberOf _
15888      * @since 3.0.0
15889      * @category Util
15890      * @param {Object} object The object to query.
15891      * @returns {Function} Returns the new accessor function.
15892      * @example
15893      *
15894      * var array = [0, 1, 2],
15895      *     object = { 'a': array, 'b': array, 'c': array };
15896      *
15897      * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15898      * // => [2, 0]
15899      *
15900      * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15901      * // => [2, 0]
15902      */
15903     function propertyOf(object) {
15904       return function(path) {
15905         return object == null ? undefined : baseGet(object, path);
15906       };
15907     }
15908
15909     /**
15910      * Creates an array of numbers (positive and/or negative) progressing from
15911      * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15912      * `start` is specified without an `end` or `step`. If `end` is not specified,
15913      * it's set to `start` with `start` then set to `0`.
15914      *
15915      * **Note:** JavaScript follows the IEEE-754 standard for resolving
15916      * floating-point values which can produce unexpected results.
15917      *
15918      * @static
15919      * @since 0.1.0
15920      * @memberOf _
15921      * @category Util
15922      * @param {number} [start=0] The start of the range.
15923      * @param {number} end The end of the range.
15924      * @param {number} [step=1] The value to increment or decrement by.
15925      * @returns {Array} Returns the range of numbers.
15926      * @see _.inRange, _.rangeRight
15927      * @example
15928      *
15929      * _.range(4);
15930      * // => [0, 1, 2, 3]
15931      *
15932      * _.range(-4);
15933      * // => [0, -1, -2, -3]
15934      *
15935      * _.range(1, 5);
15936      * // => [1, 2, 3, 4]
15937      *
15938      * _.range(0, 20, 5);
15939      * // => [0, 5, 10, 15]
15940      *
15941      * _.range(0, -4, -1);
15942      * // => [0, -1, -2, -3]
15943      *
15944      * _.range(1, 4, 0);
15945      * // => [1, 1, 1]
15946      *
15947      * _.range(0);
15948      * // => []
15949      */
15950     var range = createRange();
15951
15952     /**
15953      * This method is like `_.range` except that it populates values in
15954      * descending order.
15955      *
15956      * @static
15957      * @memberOf _
15958      * @since 4.0.0
15959      * @category Util
15960      * @param {number} [start=0] The start of the range.
15961      * @param {number} end The end of the range.
15962      * @param {number} [step=1] The value to increment or decrement by.
15963      * @returns {Array} Returns the range of numbers.
15964      * @see _.inRange, _.range
15965      * @example
15966      *
15967      * _.rangeRight(4);
15968      * // => [3, 2, 1, 0]
15969      *
15970      * _.rangeRight(-4);
15971      * // => [-3, -2, -1, 0]
15972      *
15973      * _.rangeRight(1, 5);
15974      * // => [4, 3, 2, 1]
15975      *
15976      * _.rangeRight(0, 20, 5);
15977      * // => [15, 10, 5, 0]
15978      *
15979      * _.rangeRight(0, -4, -1);
15980      * // => [-3, -2, -1, 0]
15981      *
15982      * _.rangeRight(1, 4, 0);
15983      * // => [1, 1, 1]
15984      *
15985      * _.rangeRight(0);
15986      * // => []
15987      */
15988     var rangeRight = createRange(true);
15989
15990     /**
15991      * This method returns a new empty array.
15992      *
15993      * @static
15994      * @memberOf _
15995      * @since 4.13.0
15996      * @category Util
15997      * @returns {Array} Returns the new empty array.
15998      * @example
15999      *
16000      * var arrays = _.times(2, _.stubArray);
16001      *
16002      * console.log(arrays);
16003      * // => [[], []]
16004      *
16005      * console.log(arrays[0] === arrays[1]);
16006      * // => false
16007      */
16008     function stubArray() {
16009       return [];
16010     }
16011
16012     /**
16013      * This method returns `false`.
16014      *
16015      * @static
16016      * @memberOf _
16017      * @since 4.13.0
16018      * @category Util
16019      * @returns {boolean} Returns `false`.
16020      * @example
16021      *
16022      * _.times(2, _.stubFalse);
16023      * // => [false, false]
16024      */
16025     function stubFalse() {
16026       return false;
16027     }
16028
16029     /**
16030      * This method returns a new empty object.
16031      *
16032      * @static
16033      * @memberOf _
16034      * @since 4.13.0
16035      * @category Util
16036      * @returns {Object} Returns the new empty object.
16037      * @example
16038      *
16039      * var objects = _.times(2, _.stubObject);
16040      *
16041      * console.log(objects);
16042      * // => [{}, {}]
16043      *
16044      * console.log(objects[0] === objects[1]);
16045      * // => false
16046      */
16047     function stubObject() {
16048       return {};
16049     }
16050
16051     /**
16052      * This method returns an empty string.
16053      *
16054      * @static
16055      * @memberOf _
16056      * @since 4.13.0
16057      * @category Util
16058      * @returns {string} Returns the empty string.
16059      * @example
16060      *
16061      * _.times(2, _.stubString);
16062      * // => ['', '']
16063      */
16064     function stubString() {
16065       return '';
16066     }
16067
16068     /**
16069      * This method returns `true`.
16070      *
16071      * @static
16072      * @memberOf _
16073      * @since 4.13.0
16074      * @category Util
16075      * @returns {boolean} Returns `true`.
16076      * @example
16077      *
16078      * _.times(2, _.stubTrue);
16079      * // => [true, true]
16080      */
16081     function stubTrue() {
16082       return true;
16083     }
16084
16085     /**
16086      * Invokes the iteratee `n` times, returning an array of the results of
16087      * each invocation. The iteratee is invoked with one argument; (index).
16088      *
16089      * @static
16090      * @since 0.1.0
16091      * @memberOf _
16092      * @category Util
16093      * @param {number} n The number of times to invoke `iteratee`.
16094      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16095      * @returns {Array} Returns the array of results.
16096      * @example
16097      *
16098      * _.times(3, String);
16099      * // => ['0', '1', '2']
16100      *
16101      *  _.times(4, _.constant(0));
16102      * // => [0, 0, 0, 0]
16103      */
16104     function times(n, iteratee) {
16105       n = toInteger(n);
16106       if (n < 1 || n > MAX_SAFE_INTEGER) {
16107         return [];
16108       }
16109       var index = MAX_ARRAY_LENGTH,
16110           length = nativeMin(n, MAX_ARRAY_LENGTH);
16111
16112       iteratee = getIteratee(iteratee);
16113       n -= MAX_ARRAY_LENGTH;
16114
16115       var result = baseTimes(length, iteratee);
16116       while (++index < n) {
16117         iteratee(index);
16118       }
16119       return result;
16120     }
16121
16122     /**
16123      * Converts `value` to a property path array.
16124      *
16125      * @static
16126      * @memberOf _
16127      * @since 4.0.0
16128      * @category Util
16129      * @param {*} value The value to convert.
16130      * @returns {Array} Returns the new property path array.
16131      * @example
16132      *
16133      * _.toPath('a.b.c');
16134      * // => ['a', 'b', 'c']
16135      *
16136      * _.toPath('a[0].b.c');
16137      * // => ['a', '0', 'b', 'c']
16138      */
16139     function toPath(value) {
16140       if (isArray(value)) {
16141         return arrayMap(value, toKey);
16142       }
16143       return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
16144     }
16145
16146     /**
16147      * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16148      *
16149      * @static
16150      * @since 0.1.0
16151      * @memberOf _
16152      * @category Util
16153      * @param {string} [prefix=''] The value to prefix the ID with.
16154      * @returns {string} Returns the unique ID.
16155      * @example
16156      *
16157      * _.uniqueId('contact_');
16158      * // => 'contact_104'
16159      *
16160      * _.uniqueId();
16161      * // => '105'
16162      */
16163     function uniqueId(prefix) {
16164       var id = ++idCounter;
16165       return toString(prefix) + id;
16166     }
16167
16168     /*------------------------------------------------------------------------*/
16169
16170     /**
16171      * Adds two numbers.
16172      *
16173      * @static
16174      * @memberOf _
16175      * @since 3.4.0
16176      * @category Math
16177      * @param {number} augend The first number in an addition.
16178      * @param {number} addend The second number in an addition.
16179      * @returns {number} Returns the total.
16180      * @example
16181      *
16182      * _.add(6, 4);
16183      * // => 10
16184      */
16185     var add = createMathOperation(function(augend, addend) {
16186       return augend + addend;
16187     }, 0);
16188
16189     /**
16190      * Computes `number` rounded up to `precision`.
16191      *
16192      * @static
16193      * @memberOf _
16194      * @since 3.10.0
16195      * @category Math
16196      * @param {number} number The number to round up.
16197      * @param {number} [precision=0] The precision to round up to.
16198      * @returns {number} Returns the rounded up number.
16199      * @example
16200      *
16201      * _.ceil(4.006);
16202      * // => 5
16203      *
16204      * _.ceil(6.004, 2);
16205      * // => 6.01
16206      *
16207      * _.ceil(6040, -2);
16208      * // => 6100
16209      */
16210     var ceil = createRound('ceil');
16211
16212     /**
16213      * Divide two numbers.
16214      *
16215      * @static
16216      * @memberOf _
16217      * @since 4.7.0
16218      * @category Math
16219      * @param {number} dividend The first number in a division.
16220      * @param {number} divisor The second number in a division.
16221      * @returns {number} Returns the quotient.
16222      * @example
16223      *
16224      * _.divide(6, 4);
16225      * // => 1.5
16226      */
16227     var divide = createMathOperation(function(dividend, divisor) {
16228       return dividend / divisor;
16229     }, 1);
16230
16231     /**
16232      * Computes `number` rounded down to `precision`.
16233      *
16234      * @static
16235      * @memberOf _
16236      * @since 3.10.0
16237      * @category Math
16238      * @param {number} number The number to round down.
16239      * @param {number} [precision=0] The precision to round down to.
16240      * @returns {number} Returns the rounded down number.
16241      * @example
16242      *
16243      * _.floor(4.006);
16244      * // => 4
16245      *
16246      * _.floor(0.046, 2);
16247      * // => 0.04
16248      *
16249      * _.floor(4060, -2);
16250      * // => 4000
16251      */
16252     var floor = createRound('floor');
16253
16254     /**
16255      * Computes the maximum value of `array`. If `array` is empty or falsey,
16256      * `undefined` is returned.
16257      *
16258      * @static
16259      * @since 0.1.0
16260      * @memberOf _
16261      * @category Math
16262      * @param {Array} array The array to iterate over.
16263      * @returns {*} Returns the maximum value.
16264      * @example
16265      *
16266      * _.max([4, 2, 8, 6]);
16267      * // => 8
16268      *
16269      * _.max([]);
16270      * // => undefined
16271      */
16272     function max(array) {
16273       return (array && array.length)
16274         ? baseExtremum(array, identity, baseGt)
16275         : undefined;
16276     }
16277
16278     /**
16279      * This method is like `_.max` except that it accepts `iteratee` which is
16280      * invoked for each element in `array` to generate the criterion by which
16281      * the value is ranked. The iteratee is invoked with one argument: (value).
16282      *
16283      * @static
16284      * @memberOf _
16285      * @since 4.0.0
16286      * @category Math
16287      * @param {Array} array The array to iterate over.
16288      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16289      * @returns {*} Returns the maximum value.
16290      * @example
16291      *
16292      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16293      *
16294      * _.maxBy(objects, function(o) { return o.n; });
16295      * // => { 'n': 2 }
16296      *
16297      * // The `_.property` iteratee shorthand.
16298      * _.maxBy(objects, 'n');
16299      * // => { 'n': 2 }
16300      */
16301     function maxBy(array, iteratee) {
16302       return (array && array.length)
16303         ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16304         : undefined;
16305     }
16306
16307     /**
16308      * Computes the mean of the values in `array`.
16309      *
16310      * @static
16311      * @memberOf _
16312      * @since 4.0.0
16313      * @category Math
16314      * @param {Array} array The array to iterate over.
16315      * @returns {number} Returns the mean.
16316      * @example
16317      *
16318      * _.mean([4, 2, 8, 6]);
16319      * // => 5
16320      */
16321     function mean(array) {
16322       return baseMean(array, identity);
16323     }
16324
16325     /**
16326      * This method is like `_.mean` except that it accepts `iteratee` which is
16327      * invoked for each element in `array` to generate the value to be averaged.
16328      * The iteratee is invoked with one argument: (value).
16329      *
16330      * @static
16331      * @memberOf _
16332      * @since 4.7.0
16333      * @category Math
16334      * @param {Array} array The array to iterate over.
16335      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16336      * @returns {number} Returns the mean.
16337      * @example
16338      *
16339      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16340      *
16341      * _.meanBy(objects, function(o) { return o.n; });
16342      * // => 5
16343      *
16344      * // The `_.property` iteratee shorthand.
16345      * _.meanBy(objects, 'n');
16346      * // => 5
16347      */
16348     function meanBy(array, iteratee) {
16349       return baseMean(array, getIteratee(iteratee, 2));
16350     }
16351
16352     /**
16353      * Computes the minimum value of `array`. If `array` is empty or falsey,
16354      * `undefined` is returned.
16355      *
16356      * @static
16357      * @since 0.1.0
16358      * @memberOf _
16359      * @category Math
16360      * @param {Array} array The array to iterate over.
16361      * @returns {*} Returns the minimum value.
16362      * @example
16363      *
16364      * _.min([4, 2, 8, 6]);
16365      * // => 2
16366      *
16367      * _.min([]);
16368      * // => undefined
16369      */
16370     function min(array) {
16371       return (array && array.length)
16372         ? baseExtremum(array, identity, baseLt)
16373         : undefined;
16374     }
16375
16376     /**
16377      * This method is like `_.min` except that it accepts `iteratee` which is
16378      * invoked for each element in `array` to generate the criterion by which
16379      * the value is ranked. The iteratee is invoked with one argument: (value).
16380      *
16381      * @static
16382      * @memberOf _
16383      * @since 4.0.0
16384      * @category Math
16385      * @param {Array} array The array to iterate over.
16386      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16387      * @returns {*} Returns the minimum value.
16388      * @example
16389      *
16390      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16391      *
16392      * _.minBy(objects, function(o) { return o.n; });
16393      * // => { 'n': 1 }
16394      *
16395      * // The `_.property` iteratee shorthand.
16396      * _.minBy(objects, 'n');
16397      * // => { 'n': 1 }
16398      */
16399     function minBy(array, iteratee) {
16400       return (array && array.length)
16401         ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16402         : undefined;
16403     }
16404
16405     /**
16406      * Multiply two numbers.
16407      *
16408      * @static
16409      * @memberOf _
16410      * @since 4.7.0
16411      * @category Math
16412      * @param {number} multiplier The first number in a multiplication.
16413      * @param {number} multiplicand The second number in a multiplication.
16414      * @returns {number} Returns the product.
16415      * @example
16416      *
16417      * _.multiply(6, 4);
16418      * // => 24
16419      */
16420     var multiply = createMathOperation(function(multiplier, multiplicand) {
16421       return multiplier * multiplicand;
16422     }, 1);
16423
16424     /**
16425      * Computes `number` rounded to `precision`.
16426      *
16427      * @static
16428      * @memberOf _
16429      * @since 3.10.0
16430      * @category Math
16431      * @param {number} number The number to round.
16432      * @param {number} [precision=0] The precision to round to.
16433      * @returns {number} Returns the rounded number.
16434      * @example
16435      *
16436      * _.round(4.006);
16437      * // => 4
16438      *
16439      * _.round(4.006, 2);
16440      * // => 4.01
16441      *
16442      * _.round(4060, -2);
16443      * // => 4100
16444      */
16445     var round = createRound('round');
16446
16447     /**
16448      * Subtract two numbers.
16449      *
16450      * @static
16451      * @memberOf _
16452      * @since 4.0.0
16453      * @category Math
16454      * @param {number} minuend The first number in a subtraction.
16455      * @param {number} subtrahend The second number in a subtraction.
16456      * @returns {number} Returns the difference.
16457      * @example
16458      *
16459      * _.subtract(6, 4);
16460      * // => 2
16461      */
16462     var subtract = createMathOperation(function(minuend, subtrahend) {
16463       return minuend - subtrahend;
16464     }, 0);
16465
16466     /**
16467      * Computes the sum of the values in `array`.
16468      *
16469      * @static
16470      * @memberOf _
16471      * @since 3.4.0
16472      * @category Math
16473      * @param {Array} array The array to iterate over.
16474      * @returns {number} Returns the sum.
16475      * @example
16476      *
16477      * _.sum([4, 2, 8, 6]);
16478      * // => 20
16479      */
16480     function sum(array) {
16481       return (array && array.length)
16482         ? baseSum(array, identity)
16483         : 0;
16484     }
16485
16486     /**
16487      * This method is like `_.sum` except that it accepts `iteratee` which is
16488      * invoked for each element in `array` to generate the value to be summed.
16489      * The iteratee is invoked with one argument: (value).
16490      *
16491      * @static
16492      * @memberOf _
16493      * @since 4.0.0
16494      * @category Math
16495      * @param {Array} array The array to iterate over.
16496      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16497      * @returns {number} Returns the sum.
16498      * @example
16499      *
16500      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16501      *
16502      * _.sumBy(objects, function(o) { return o.n; });
16503      * // => 20
16504      *
16505      * // The `_.property` iteratee shorthand.
16506      * _.sumBy(objects, 'n');
16507      * // => 20
16508      */
16509     function sumBy(array, iteratee) {
16510       return (array && array.length)
16511         ? baseSum(array, getIteratee(iteratee, 2))
16512         : 0;
16513     }
16514
16515     /*------------------------------------------------------------------------*/
16516
16517     // Add methods that return wrapped values in chain sequences.
16518     lodash.after = after;
16519     lodash.ary = ary;
16520     lodash.assign = assign;
16521     lodash.assignIn = assignIn;
16522     lodash.assignInWith = assignInWith;
16523     lodash.assignWith = assignWith;
16524     lodash.at = at;
16525     lodash.before = before;
16526     lodash.bind = bind;
16527     lodash.bindAll = bindAll;
16528     lodash.bindKey = bindKey;
16529     lodash.castArray = castArray;
16530     lodash.chain = chain;
16531     lodash.chunk = chunk;
16532     lodash.compact = compact;
16533     lodash.concat = concat;
16534     lodash.cond = cond;
16535     lodash.conforms = conforms;
16536     lodash.constant = constant;
16537     lodash.countBy = countBy;
16538     lodash.create = create;
16539     lodash.curry = curry;
16540     lodash.curryRight = curryRight;
16541     lodash.debounce = debounce;
16542     lodash.defaults = defaults;
16543     lodash.defaultsDeep = defaultsDeep;
16544     lodash.defer = defer;
16545     lodash.delay = delay;
16546     lodash.difference = difference;
16547     lodash.differenceBy = differenceBy;
16548     lodash.differenceWith = differenceWith;
16549     lodash.drop = drop;
16550     lodash.dropRight = dropRight;
16551     lodash.dropRightWhile = dropRightWhile;
16552     lodash.dropWhile = dropWhile;
16553     lodash.fill = fill;
16554     lodash.filter = filter;
16555     lodash.flatMap = flatMap;
16556     lodash.flatMapDeep = flatMapDeep;
16557     lodash.flatMapDepth = flatMapDepth;
16558     lodash.flatten = flatten;
16559     lodash.flattenDeep = flattenDeep;
16560     lodash.flattenDepth = flattenDepth;
16561     lodash.flip = flip;
16562     lodash.flow = flow;
16563     lodash.flowRight = flowRight;
16564     lodash.fromPairs = fromPairs;
16565     lodash.functions = functions;
16566     lodash.functionsIn = functionsIn;
16567     lodash.groupBy = groupBy;
16568     lodash.initial = initial;
16569     lodash.intersection = intersection;
16570     lodash.intersectionBy = intersectionBy;
16571     lodash.intersectionWith = intersectionWith;
16572     lodash.invert = invert;
16573     lodash.invertBy = invertBy;
16574     lodash.invokeMap = invokeMap;
16575     lodash.iteratee = iteratee;
16576     lodash.keyBy = keyBy;
16577     lodash.keys = keys;
16578     lodash.keysIn = keysIn;
16579     lodash.map = map;
16580     lodash.mapKeys = mapKeys;
16581     lodash.mapValues = mapValues;
16582     lodash.matches = matches;
16583     lodash.matchesProperty = matchesProperty;
16584     lodash.memoize = memoize;
16585     lodash.merge = merge;
16586     lodash.mergeWith = mergeWith;
16587     lodash.method = method;
16588     lodash.methodOf = methodOf;
16589     lodash.mixin = mixin;
16590     lodash.negate = negate;
16591     lodash.nthArg = nthArg;
16592     lodash.omit = omit;
16593     lodash.omitBy = omitBy;
16594     lodash.once = once;
16595     lodash.orderBy = orderBy;
16596     lodash.over = over;
16597     lodash.overArgs = overArgs;
16598     lodash.overEvery = overEvery;
16599     lodash.overSome = overSome;
16600     lodash.partial = partial;
16601     lodash.partialRight = partialRight;
16602     lodash.partition = partition;
16603     lodash.pick = pick;
16604     lodash.pickBy = pickBy;
16605     lodash.property = property;
16606     lodash.propertyOf = propertyOf;
16607     lodash.pull = pull;
16608     lodash.pullAll = pullAll;
16609     lodash.pullAllBy = pullAllBy;
16610     lodash.pullAllWith = pullAllWith;
16611     lodash.pullAt = pullAt;
16612     lodash.range = range;
16613     lodash.rangeRight = rangeRight;
16614     lodash.rearg = rearg;
16615     lodash.reject = reject;
16616     lodash.remove = remove;
16617     lodash.rest = rest;
16618     lodash.reverse = reverse;
16619     lodash.sampleSize = sampleSize;
16620     lodash.set = set;
16621     lodash.setWith = setWith;
16622     lodash.shuffle = shuffle;
16623     lodash.slice = slice;
16624     lodash.sortBy = sortBy;
16625     lodash.sortedUniq = sortedUniq;
16626     lodash.sortedUniqBy = sortedUniqBy;
16627     lodash.split = split;
16628     lodash.spread = spread;
16629     lodash.tail = tail;
16630     lodash.take = take;
16631     lodash.takeRight = takeRight;
16632     lodash.takeRightWhile = takeRightWhile;
16633     lodash.takeWhile = takeWhile;
16634     lodash.tap = tap;
16635     lodash.throttle = throttle;
16636     lodash.thru = thru;
16637     lodash.toArray = toArray;
16638     lodash.toPairs = toPairs;
16639     lodash.toPairsIn = toPairsIn;
16640     lodash.toPath = toPath;
16641     lodash.toPlainObject = toPlainObject;
16642     lodash.transform = transform;
16643     lodash.unary = unary;
16644     lodash.union = union;
16645     lodash.unionBy = unionBy;
16646     lodash.unionWith = unionWith;
16647     lodash.uniq = uniq;
16648     lodash.uniqBy = uniqBy;
16649     lodash.uniqWith = uniqWith;
16650     lodash.unset = unset;
16651     lodash.unzip = unzip;
16652     lodash.unzipWith = unzipWith;
16653     lodash.update = update;
16654     lodash.updateWith = updateWith;
16655     lodash.values = values;
16656     lodash.valuesIn = valuesIn;
16657     lodash.without = without;
16658     lodash.words = words;
16659     lodash.wrap = wrap;
16660     lodash.xor = xor;
16661     lodash.xorBy = xorBy;
16662     lodash.xorWith = xorWith;
16663     lodash.zip = zip;
16664     lodash.zipObject = zipObject;
16665     lodash.zipObjectDeep = zipObjectDeep;
16666     lodash.zipWith = zipWith;
16667
16668     // Add aliases.
16669     lodash.entries = toPairs;
16670     lodash.entriesIn = toPairsIn;
16671     lodash.extend = assignIn;
16672     lodash.extendWith = assignInWith;
16673
16674     // Add methods to `lodash.prototype`.
16675     mixin(lodash, lodash);
16676
16677     /*------------------------------------------------------------------------*/
16678
16679     // Add methods that return unwrapped values in chain sequences.
16680     lodash.add = add;
16681     lodash.attempt = attempt;
16682     lodash.camelCase = camelCase;
16683     lodash.capitalize = capitalize;
16684     lodash.ceil = ceil;
16685     lodash.clamp = clamp;
16686     lodash.clone = clone;
16687     lodash.cloneDeep = cloneDeep;
16688     lodash.cloneDeepWith = cloneDeepWith;
16689     lodash.cloneWith = cloneWith;
16690     lodash.conformsTo = conformsTo;
16691     lodash.deburr = deburr;
16692     lodash.defaultTo = defaultTo;
16693     lodash.divide = divide;
16694     lodash.endsWith = endsWith;
16695     lodash.eq = eq;
16696     lodash.escape = escape;
16697     lodash.escapeRegExp = escapeRegExp;
16698     lodash.every = every;
16699     lodash.find = find;
16700     lodash.findIndex = findIndex;
16701     lodash.findKey = findKey;
16702     lodash.findLast = findLast;
16703     lodash.findLastIndex = findLastIndex;
16704     lodash.findLastKey = findLastKey;
16705     lodash.floor = floor;
16706     lodash.forEach = forEach;
16707     lodash.forEachRight = forEachRight;
16708     lodash.forIn = forIn;
16709     lodash.forInRight = forInRight;
16710     lodash.forOwn = forOwn;
16711     lodash.forOwnRight = forOwnRight;
16712     lodash.get = get;
16713     lodash.gt = gt;
16714     lodash.gte = gte;
16715     lodash.has = has;
16716     lodash.hasIn = hasIn;
16717     lodash.head = head;
16718     lodash.identity = identity;
16719     lodash.includes = includes;
16720     lodash.indexOf = indexOf;
16721     lodash.inRange = inRange;
16722     lodash.invoke = invoke;
16723     lodash.isArguments = isArguments;
16724     lodash.isArray = isArray;
16725     lodash.isArrayBuffer = isArrayBuffer;
16726     lodash.isArrayLike = isArrayLike;
16727     lodash.isArrayLikeObject = isArrayLikeObject;
16728     lodash.isBoolean = isBoolean;
16729     lodash.isBuffer = isBuffer;
16730     lodash.isDate = isDate;
16731     lodash.isElement = isElement;
16732     lodash.isEmpty = isEmpty;
16733     lodash.isEqual = isEqual;
16734     lodash.isEqualWith = isEqualWith;
16735     lodash.isError = isError;
16736     lodash.isFinite = isFinite;
16737     lodash.isFunction = isFunction;
16738     lodash.isInteger = isInteger;
16739     lodash.isLength = isLength;
16740     lodash.isMap = isMap;
16741     lodash.isMatch = isMatch;
16742     lodash.isMatchWith = isMatchWith;
16743     lodash.isNaN = isNaN;
16744     lodash.isNative = isNative;
16745     lodash.isNil = isNil;
16746     lodash.isNull = isNull;
16747     lodash.isNumber = isNumber;
16748     lodash.isObject = isObject;
16749     lodash.isObjectLike = isObjectLike;
16750     lodash.isPlainObject = isPlainObject;
16751     lodash.isRegExp = isRegExp;
16752     lodash.isSafeInteger = isSafeInteger;
16753     lodash.isSet = isSet;
16754     lodash.isString = isString;
16755     lodash.isSymbol = isSymbol;
16756     lodash.isTypedArray = isTypedArray;
16757     lodash.isUndefined = isUndefined;
16758     lodash.isWeakMap = isWeakMap;
16759     lodash.isWeakSet = isWeakSet;
16760     lodash.join = join;
16761     lodash.kebabCase = kebabCase;
16762     lodash.last = last;
16763     lodash.lastIndexOf = lastIndexOf;
16764     lodash.lowerCase = lowerCase;
16765     lodash.lowerFirst = lowerFirst;
16766     lodash.lt = lt;
16767     lodash.lte = lte;
16768     lodash.max = max;
16769     lodash.maxBy = maxBy;
16770     lodash.mean = mean;
16771     lodash.meanBy = meanBy;
16772     lodash.min = min;
16773     lodash.minBy = minBy;
16774     lodash.stubArray = stubArray;
16775     lodash.stubFalse = stubFalse;
16776     lodash.stubObject = stubObject;
16777     lodash.stubString = stubString;
16778     lodash.stubTrue = stubTrue;
16779     lodash.multiply = multiply;
16780     lodash.nth = nth;
16781     lodash.noConflict = noConflict;
16782     lodash.noop = noop;
16783     lodash.now = now;
16784     lodash.pad = pad;
16785     lodash.padEnd = padEnd;
16786     lodash.padStart = padStart;
16787     lodash.parseInt = parseInt;
16788     lodash.random = random;
16789     lodash.reduce = reduce;
16790     lodash.reduceRight = reduceRight;
16791     lodash.repeat = repeat;
16792     lodash.replace = replace;
16793     lodash.result = result;
16794     lodash.round = round;
16795     lodash.runInContext = runInContext;
16796     lodash.sample = sample;
16797     lodash.size = size;
16798     lodash.snakeCase = snakeCase;
16799     lodash.some = some;
16800     lodash.sortedIndex = sortedIndex;
16801     lodash.sortedIndexBy = sortedIndexBy;
16802     lodash.sortedIndexOf = sortedIndexOf;
16803     lodash.sortedLastIndex = sortedLastIndex;
16804     lodash.sortedLastIndexBy = sortedLastIndexBy;
16805     lodash.sortedLastIndexOf = sortedLastIndexOf;
16806     lodash.startCase = startCase;
16807     lodash.startsWith = startsWith;
16808     lodash.subtract = subtract;
16809     lodash.sum = sum;
16810     lodash.sumBy = sumBy;
16811     lodash.template = template;
16812     lodash.times = times;
16813     lodash.toFinite = toFinite;
16814     lodash.toInteger = toInteger;
16815     lodash.toLength = toLength;
16816     lodash.toLower = toLower;
16817     lodash.toNumber = toNumber;
16818     lodash.toSafeInteger = toSafeInteger;
16819     lodash.toString = toString;
16820     lodash.toUpper = toUpper;
16821     lodash.trim = trim;
16822     lodash.trimEnd = trimEnd;
16823     lodash.trimStart = trimStart;
16824     lodash.truncate = truncate;
16825     lodash.unescape = unescape;
16826     lodash.uniqueId = uniqueId;
16827     lodash.upperCase = upperCase;
16828     lodash.upperFirst = upperFirst;
16829
16830     // Add aliases.
16831     lodash.each = forEach;
16832     lodash.eachRight = forEachRight;
16833     lodash.first = head;
16834
16835     mixin(lodash, (function() {
16836       var source = {};
16837       baseForOwn(lodash, function(func, methodName) {
16838         if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16839           source[methodName] = func;
16840         }
16841       });
16842       return source;
16843     }()), { 'chain': false });
16844
16845     /*------------------------------------------------------------------------*/
16846
16847     /**
16848      * The semantic version number.
16849      *
16850      * @static
16851      * @memberOf _
16852      * @type {string}
16853      */
16854     lodash.VERSION = VERSION;
16855
16856     // Assign default placeholders.
16857     arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16858       lodash[methodName].placeholder = lodash;
16859     });
16860
16861     // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16862     arrayEach(['drop', 'take'], function(methodName, index) {
16863       LazyWrapper.prototype[methodName] = function(n) {
16864         n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16865
16866         var result = (this.__filtered__ && !index)
16867           ? new LazyWrapper(this)
16868           : this.clone();
16869
16870         if (result.__filtered__) {
16871           result.__takeCount__ = nativeMin(n, result.__takeCount__);
16872         } else {
16873           result.__views__.push({
16874             'size': nativeMin(n, MAX_ARRAY_LENGTH),
16875             'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16876           });
16877         }
16878         return result;
16879       };
16880
16881       LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16882         return this.reverse()[methodName](n).reverse();
16883       };
16884     });
16885
16886     // Add `LazyWrapper` methods that accept an `iteratee` value.
16887     arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16888       var type = index + 1,
16889           isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16890
16891       LazyWrapper.prototype[methodName] = function(iteratee) {
16892         var result = this.clone();
16893         result.__iteratees__.push({
16894           'iteratee': getIteratee(iteratee, 3),
16895           'type': type
16896         });
16897         result.__filtered__ = result.__filtered__ || isFilter;
16898         return result;
16899       };
16900     });
16901
16902     // Add `LazyWrapper` methods for `_.head` and `_.last`.
16903     arrayEach(['head', 'last'], function(methodName, index) {
16904       var takeName = 'take' + (index ? 'Right' : '');
16905
16906       LazyWrapper.prototype[methodName] = function() {
16907         return this[takeName](1).value()[0];
16908       };
16909     });
16910
16911     // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16912     arrayEach(['initial', 'tail'], function(methodName, index) {
16913       var dropName = 'drop' + (index ? '' : 'Right');
16914
16915       LazyWrapper.prototype[methodName] = function() {
16916         return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16917       };
16918     });
16919
16920     LazyWrapper.prototype.compact = function() {
16921       return this.filter(identity);
16922     };
16923
16924     LazyWrapper.prototype.find = function(predicate) {
16925       return this.filter(predicate).head();
16926     };
16927
16928     LazyWrapper.prototype.findLast = function(predicate) {
16929       return this.reverse().find(predicate);
16930     };
16931
16932     LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16933       if (typeof path == 'function') {
16934         return new LazyWrapper(this);
16935       }
16936       return this.map(function(value) {
16937         return baseInvoke(value, path, args);
16938       });
16939     });
16940
16941     LazyWrapper.prototype.reject = function(predicate) {
16942       return this.filter(negate(getIteratee(predicate)));
16943     };
16944
16945     LazyWrapper.prototype.slice = function(start, end) {
16946       start = toInteger(start);
16947
16948       var result = this;
16949       if (result.__filtered__ && (start > 0 || end < 0)) {
16950         return new LazyWrapper(result);
16951       }
16952       if (start < 0) {
16953         result = result.takeRight(-start);
16954       } else if (start) {
16955         result = result.drop(start);
16956       }
16957       if (end !== undefined) {
16958         end = toInteger(end);
16959         result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16960       }
16961       return result;
16962     };
16963
16964     LazyWrapper.prototype.takeRightWhile = function(predicate) {
16965       return this.reverse().takeWhile(predicate).reverse();
16966     };
16967
16968     LazyWrapper.prototype.toArray = function() {
16969       return this.take(MAX_ARRAY_LENGTH);
16970     };
16971
16972     // Add `LazyWrapper` methods to `lodash.prototype`.
16973     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16974       var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16975           isTaker = /^(?:head|last)$/.test(methodName),
16976           lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16977           retUnwrapped = isTaker || /^find/.test(methodName);
16978
16979       if (!lodashFunc) {
16980         return;
16981       }
16982       lodash.prototype[methodName] = function() {
16983         var value = this.__wrapped__,
16984             args = isTaker ? [1] : arguments,
16985             isLazy = value instanceof LazyWrapper,
16986             iteratee = args[0],
16987             useLazy = isLazy || isArray(value);
16988
16989         var interceptor = function(value) {
16990           var result = lodashFunc.apply(lodash, arrayPush([value], args));
16991           return (isTaker && chainAll) ? result[0] : result;
16992         };
16993
16994         if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16995           // Avoid lazy use if the iteratee has a "length" value other than `1`.
16996           isLazy = useLazy = false;
16997         }
16998         var chainAll = this.__chain__,
16999             isHybrid = !!this.__actions__.length,
17000             isUnwrapped = retUnwrapped && !chainAll,
17001             onlyLazy = isLazy && !isHybrid;
17002
17003         if (!retUnwrapped && useLazy) {
17004           value = onlyLazy ? value : new LazyWrapper(this);
17005           var result = func.apply(value, args);
17006           result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
17007           return new LodashWrapper(result, chainAll);
17008         }
17009         if (isUnwrapped && onlyLazy) {
17010           return func.apply(this, args);
17011         }
17012         result = this.thru(interceptor);
17013         return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
17014       };
17015     });
17016
17017     // Add `Array` methods to `lodash.prototype`.
17018     arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17019       var func = arrayProto[methodName],
17020           chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17021           retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17022
17023       lodash.prototype[methodName] = function() {
17024         var args = arguments;
17025         if (retUnwrapped && !this.__chain__) {
17026           var value = this.value();
17027           return func.apply(isArray(value) ? value : [], args);
17028         }
17029         return this[chainName](function(value) {
17030           return func.apply(isArray(value) ? value : [], args);
17031         });
17032       };
17033     });
17034
17035     // Map minified method names to their real names.
17036     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17037       var lodashFunc = lodash[methodName];
17038       if (lodashFunc) {
17039         var key = (lodashFunc.name + ''),
17040             names = realNames[key] || (realNames[key] = []);
17041
17042         names.push({ 'name': methodName, 'func': lodashFunc });
17043       }
17044     });
17045
17046     realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17047       'name': 'wrapper',
17048       'func': undefined
17049     }];
17050
17051     // Add methods to `LazyWrapper`.
17052     LazyWrapper.prototype.clone = lazyClone;
17053     LazyWrapper.prototype.reverse = lazyReverse;
17054     LazyWrapper.prototype.value = lazyValue;
17055
17056     // Add chain sequence methods to the `lodash` wrapper.
17057     lodash.prototype.at = wrapperAt;
17058     lodash.prototype.chain = wrapperChain;
17059     lodash.prototype.commit = wrapperCommit;
17060     lodash.prototype.next = wrapperNext;
17061     lodash.prototype.plant = wrapperPlant;
17062     lodash.prototype.reverse = wrapperReverse;
17063     lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17064
17065     // Add lazy aliases.
17066     lodash.prototype.first = lodash.prototype.head;
17067
17068     if (symIterator) {
17069       lodash.prototype[symIterator] = wrapperToIterator;
17070     }
17071     return lodash;
17072   });
17073
17074   /*--------------------------------------------------------------------------*/
17075
17076   // Export lodash.
17077   var _ = runInContext();
17078
17079   // Some AMD build optimizers, like r.js, check for condition patterns like:
17080   if (typeof undefined == 'function' && typeof undefined.amd == 'object' && undefined.amd) {
17081     // Expose Lodash on the global object to prevent errors when Lodash is
17082     // loaded by a script tag in the presence of an AMD loader.
17083     // See http://requirejs.org/docs/errors.html#mismatch for more details.
17084     // Use `_.noConflict` to remove Lodash from the global object.
17085     root._ = _;
17086
17087     // Define as an anonymous module so, through path mapping, it can be
17088     // referenced as the "underscore" module.
17089     undefined(function() {
17090       return _;
17091     });
17092   }
17093   // Check for `exports` after `define` in case a build optimizer adds it.
17094   else if (freeModule) {
17095     // Export for Node.js.
17096     (freeModule.exports = _)._ = _;
17097     // Export for CommonJS support.
17098     freeExports._ = _;
17099   }
17100   else {
17101     // Export to the global object.
17102     root._ = _;
17103   }
17104 }.call(commonjsGlobal));
17105 });
17106
17107 function osmIsInterestingTag(key) {
17108     return key !== 'attribution' &&
17109         key !== 'created_by' &&
17110         key !== 'source' &&
17111         key !== 'odbl' &&
17112         key.indexOf('tiger:') !== 0;
17113
17114 }
17115
17116
17117 var osmOneWayTags = {
17118     'aerialway': {
17119         'chair_lift': true,
17120         'mixed_lift': true,
17121         't-bar': true,
17122         'j-bar': true,
17123         'platter': true,
17124         'rope_tow': true,
17125         'magic_carpet': true,
17126         'yes': true
17127     },
17128     'highway': {
17129         'motorway': true,
17130         'motorway_link': true
17131     },
17132     'junction': {
17133         'roundabout': true
17134     },
17135     'man_made': {
17136         'piste:halfpipe': true
17137     },
17138     'piste:type': {
17139         'downhill': true,
17140         'sled': true,
17141         'yes': true
17142     },
17143     'waterway': {
17144         'river': true,
17145         'stream': true
17146     }
17147 };
17148
17149
17150 var osmPavedTags = {
17151     'surface': {
17152         'paved': true,
17153         'asphalt': true,
17154         'concrete': true
17155     },
17156     'tracktype': {
17157         'grade1': true
17158     }
17159 };
17160
17161 var dataWikipedia = [
17162     [
17163         "Abkhazian",
17164         "Аҧсшәа",
17165         "ab"
17166     ],
17167     [
17168         "Achinese",
17169         "Acèh",
17170         "ace"
17171     ],
17172     [
17173         "Adyghe",
17174         "адыгабзэ",
17175         "ady"
17176     ],
17177     [
17178         "Afrikaans",
17179         "Afrikaans",
17180         "af"
17181     ],
17182     [
17183         "Akan",
17184         "Akan",
17185         "ak"
17186     ],
17187     [
17188         "Alemannisch",
17189         "Alemannisch",
17190         "als"
17191     ],
17192     [
17193         "Amharic",
17194         "አማርኛ",
17195         "am"
17196     ],
17197     [
17198         "Aragonese",
17199         "aragonés",
17200         "an"
17201     ],
17202     [
17203         "Old English",
17204         "Ænglisc",
17205         "ang"
17206     ],
17207     [
17208         "Arabic",
17209         "العربية",
17210         "ar"
17211     ],
17212     [
17213         "Aramaic",
17214         "ܐܪܡܝܐ",
17215         "arc"
17216     ],
17217     [
17218         "Egyptian Arabic",
17219         "مصرى",
17220         "arz"
17221     ],
17222     [
17223         "Assamese",
17224         "অসমীয়া",
17225         "as"
17226     ],
17227     [
17228         "Asturian",
17229         "asturianu",
17230         "ast"
17231     ],
17232     [
17233         "Avaric",
17234         "авар",
17235         "av"
17236     ],
17237     [
17238         "Aymara",
17239         "Aymar aru",
17240         "ay"
17241     ],
17242     [
17243         "Azerbaijani",
17244         "azərbaycanca",
17245         "az"
17246     ],
17247     [
17248         "تۆرکجه",
17249         "تۆرکجه",
17250         "azb"
17251     ],
17252     [
17253         "Bashkir",
17254         "башҡортса",
17255         "ba"
17256     ],
17257     [
17258         "Bavarian",
17259         "Boarisch",
17260         "bar"
17261     ],
17262     [
17263         "Samogitian",
17264         "žemaitėška",
17265         "bat-smg"
17266     ],
17267     [
17268         "Bikol Central",
17269         "Bikol Central",
17270         "bcl"
17271     ],
17272     [
17273         "Belarusian",
17274         "беларуская",
17275         "be"
17276     ],
17277     [
17278         "беларуская (тарашкевіца)‎",
17279         "беларуская (тарашкевіца)‎",
17280         "be-x-old"
17281     ],
17282     [
17283         "Bulgarian",
17284         "български",
17285         "bg"
17286     ],
17287     [
17288         "भोजपुरी",
17289         "भोजपुरी",
17290         "bh"
17291     ],
17292     [
17293         "Bislama",
17294         "Bislama",
17295         "bi"
17296     ],
17297     [
17298         "Banjar",
17299         "Bahasa Banjar",
17300         "bjn"
17301     ],
17302     [
17303         "Bambara",
17304         "bamanankan",
17305         "bm"
17306     ],
17307     [
17308         "Bengali",
17309         "বাংলা",
17310         "bn"
17311     ],
17312     [
17313         "Tibetan",
17314         "བོད་ཡིག",
17315         "bo"
17316     ],
17317     [
17318         "Bishnupriya",
17319         "বিষ্ণুপ্রিয়া মণিপুরী",
17320         "bpy"
17321     ],
17322     [
17323         "Breton",
17324         "brezhoneg",
17325         "br"
17326     ],
17327     [
17328         "Bosnian",
17329         "bosanski",
17330         "bs"
17331     ],
17332     [
17333         "Buginese",
17334         "ᨅᨔ ᨕᨘᨁᨗ",
17335         "bug"
17336     ],
17337     [
17338         "буряад",
17339         "буряад",
17340         "bxr"
17341     ],
17342     [
17343         "Catalan",
17344         "català",
17345         "ca"
17346     ],
17347     [
17348         "Chavacano de Zamboanga",
17349         "Chavacano de Zamboanga",
17350         "cbk-zam"
17351     ],
17352     [
17353         "Min Dong Chinese",
17354         "Mìng-dĕ̤ng-ngṳ̄",
17355         "cdo"
17356     ],
17357     [
17358         "Chechen",
17359         "нохчийн",
17360         "ce"
17361     ],
17362     [
17363         "Cebuano",
17364         "Cebuano",
17365         "ceb"
17366     ],
17367     [
17368         "Chamorro",
17369         "Chamoru",
17370         "ch"
17371     ],
17372     [
17373         "Cherokee",
17374         "ᏣᎳᎩ",
17375         "chr"
17376     ],
17377     [
17378         "Cheyenne",
17379         "Tsetsêhestâhese",
17380         "chy"
17381     ],
17382     [
17383         "Central Kurdish",
17384         "کوردیی ناوەندی",
17385         "ckb"
17386     ],
17387     [
17388         "Corsican",
17389         "corsu",
17390         "co"
17391     ],
17392     [
17393         "Cree",
17394         "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17395         "cr"
17396     ],
17397     [
17398         "Crimean Turkish",
17399         "qırımtatarca",
17400         "crh"
17401     ],
17402     [
17403         "Czech",
17404         "čeština",
17405         "cs"
17406     ],
17407     [
17408         "Kashubian",
17409         "kaszëbsczi",
17410         "csb"
17411     ],
17412     [
17413         "Church Slavic",
17414         "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17415         "cu"
17416     ],
17417     [
17418         "Chuvash",
17419         "Чӑвашла",
17420         "cv"
17421     ],
17422     [
17423         "Welsh",
17424         "Cymraeg",
17425         "cy"
17426     ],
17427     [
17428         "Danish",
17429         "dansk",
17430         "da"
17431     ],
17432     [
17433         "German",
17434         "Deutsch",
17435         "de"
17436     ],
17437     [
17438         "Zazaki",
17439         "Zazaki",
17440         "diq"
17441     ],
17442     [
17443         "Lower Sorbian",
17444         "dolnoserbski",
17445         "dsb"
17446     ],
17447     [
17448         "Divehi",
17449         "ދިވެހިބަސް",
17450         "dv"
17451     ],
17452     [
17453         "Dzongkha",
17454         "ཇོང་ཁ",
17455         "dz"
17456     ],
17457     [
17458         "Ewe",
17459         "eʋegbe",
17460         "ee"
17461     ],
17462     [
17463         "Greek",
17464         "Ελληνικά",
17465         "el"
17466     ],
17467     [
17468         "Emiliano-Romagnolo",
17469         "emiliàn e rumagnòl",
17470         "eml"
17471     ],
17472     [
17473         "English",
17474         "English",
17475         "en"
17476     ],
17477     [
17478         "Esperanto",
17479         "Esperanto",
17480         "eo"
17481     ],
17482     [
17483         "Spanish",
17484         "español",
17485         "es"
17486     ],
17487     [
17488         "Estonian",
17489         "eesti",
17490         "et"
17491     ],
17492     [
17493         "Basque",
17494         "euskara",
17495         "eu"
17496     ],
17497     [
17498         "Extremaduran",
17499         "estremeñu",
17500         "ext"
17501     ],
17502     [
17503         "Persian",
17504         "فارسی",
17505         "fa"
17506     ],
17507     [
17508         "Fulah",
17509         "Fulfulde",
17510         "ff"
17511     ],
17512     [
17513         "Finnish",
17514         "suomi",
17515         "fi"
17516     ],
17517     [
17518         "Võro",
17519         "Võro",
17520         "fiu-vro"
17521     ],
17522     [
17523         "Fijian",
17524         "Na Vosa Vakaviti",
17525         "fj"
17526     ],
17527     [
17528         "Faroese",
17529         "føroyskt",
17530         "fo"
17531     ],
17532     [
17533         "French",
17534         "français",
17535         "fr"
17536     ],
17537     [
17538         "Arpitan",
17539         "arpetan",
17540         "frp"
17541     ],
17542     [
17543         "Northern Frisian",
17544         "Nordfriisk",
17545         "frr"
17546     ],
17547     [
17548         "Friulian",
17549         "furlan",
17550         "fur"
17551     ],
17552     [
17553         "Western Frisian",
17554         "Frysk",
17555         "fy"
17556     ],
17557     [
17558         "Irish",
17559         "Gaeilge",
17560         "ga"
17561     ],
17562     [
17563         "Gagauz",
17564         "Gagauz",
17565         "gag"
17566     ],
17567     [
17568         "Gan Chinese",
17569         "贛語",
17570         "gan"
17571     ],
17572     [
17573         "Scottish Gaelic",
17574         "Gàidhlig",
17575         "gd"
17576     ],
17577     [
17578         "Galician",
17579         "galego",
17580         "gl"
17581     ],
17582     [
17583         "Gilaki",
17584         "گیلکی",
17585         "glk"
17586     ],
17587     [
17588         "Guarani",
17589         "Avañe'ẽ",
17590         "gn"
17591     ],
17592     [
17593         "Goan Konkani",
17594         "गोंयची कोंकणी / Gõychi Konknni",
17595         "gom"
17596     ],
17597     [
17598         "Gothic",
17599         "𐌲𐌿𐍄𐌹𐍃𐌺",
17600         "got"
17601     ],
17602     [
17603         "Gujarati",
17604         "ગુજરાતી",
17605         "gu"
17606     ],
17607     [
17608         "Manx",
17609         "Gaelg",
17610         "gv"
17611     ],
17612     [
17613         "Hausa",
17614         "Hausa",
17615         "ha"
17616     ],
17617     [
17618         "Hakka Chinese",
17619         "客家語/Hak-kâ-ngî",
17620         "hak"
17621     ],
17622     [
17623         "Hawaiian",
17624         "Hawaiʻi",
17625         "haw"
17626     ],
17627     [
17628         "Hebrew",
17629         "עברית",
17630         "he"
17631     ],
17632     [
17633         "Hindi",
17634         "हिन्दी",
17635         "hi"
17636     ],
17637     [
17638         "Fiji Hindi",
17639         "Fiji Hindi",
17640         "hif"
17641     ],
17642     [
17643         "Croatian",
17644         "hrvatski",
17645         "hr"
17646     ],
17647     [
17648         "Upper Sorbian",
17649         "hornjoserbsce",
17650         "hsb"
17651     ],
17652     [
17653         "Haitian Creole",
17654         "Kreyòl ayisyen",
17655         "ht"
17656     ],
17657     [
17658         "Hungarian",
17659         "magyar",
17660         "hu"
17661     ],
17662     [
17663         "Armenian",
17664         "Հայերեն",
17665         "hy"
17666     ],
17667     [
17668         "Interlingua",
17669         "interlingua",
17670         "ia"
17671     ],
17672     [
17673         "Indonesian",
17674         "Bahasa Indonesia",
17675         "id"
17676     ],
17677     [
17678         "Interlingue",
17679         "Interlingue",
17680         "ie"
17681     ],
17682     [
17683         "Igbo",
17684         "Igbo",
17685         "ig"
17686     ],
17687     [
17688         "Inupiaq",
17689         "Iñupiak",
17690         "ik"
17691     ],
17692     [
17693         "Iloko",
17694         "Ilokano",
17695         "ilo"
17696     ],
17697     [
17698         "Ido",
17699         "Ido",
17700         "io"
17701     ],
17702     [
17703         "Icelandic",
17704         "íslenska",
17705         "is"
17706     ],
17707     [
17708         "Italian",
17709         "italiano",
17710         "it"
17711     ],
17712     [
17713         "Inuktitut",
17714         "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17715         "iu"
17716     ],
17717     [
17718         "Japanese",
17719         "日本語",
17720         "ja"
17721     ],
17722     [
17723         "Jamaican Creole English",
17724         "Patois",
17725         "jam"
17726     ],
17727     [
17728         "Lojban",
17729         "la .lojban.",
17730         "jbo"
17731     ],
17732     [
17733         "Javanese",
17734         "Basa Jawa",
17735         "jv"
17736     ],
17737     [
17738         "Georgian",
17739         "ქართული",
17740         "ka"
17741     ],
17742     [
17743         "Kara-Kalpak",
17744         "Qaraqalpaqsha",
17745         "kaa"
17746     ],
17747     [
17748         "Kabyle",
17749         "Taqbaylit",
17750         "kab"
17751     ],
17752     [
17753         "Kabardian",
17754         "Адыгэбзэ",
17755         "kbd"
17756     ],
17757     [
17758         "Kongo",
17759         "Kongo",
17760         "kg"
17761     ],
17762     [
17763         "Kikuyu",
17764         "Gĩkũyũ",
17765         "ki"
17766     ],
17767     [
17768         "Kazakh",
17769         "қазақша",
17770         "kk"
17771     ],
17772     [
17773         "Kalaallisut",
17774         "kalaallisut",
17775         "kl"
17776     ],
17777     [
17778         "Khmer",
17779         "ភាសាខ្មែរ",
17780         "km"
17781     ],
17782     [
17783         "Kannada",
17784         "ಕನ್ನಡ",
17785         "kn"
17786     ],
17787     [
17788         "Korean",
17789         "한국어",
17790         "ko"
17791     ],
17792     [
17793         "Komi-Permyak",
17794         "Перем Коми",
17795         "koi"
17796     ],
17797     [
17798         "Karachay-Balkar",
17799         "къарачай-малкъар",
17800         "krc"
17801     ],
17802     [
17803         "Kashmiri",
17804         "कॉशुर / کٲشُر",
17805         "ks"
17806     ],
17807     [
17808         "Colognian",
17809         "Ripoarisch",
17810         "ksh"
17811     ],
17812     [
17813         "Kurdish",
17814         "Kurdî",
17815         "ku"
17816     ],
17817     [
17818         "Komi",
17819         "коми",
17820         "kv"
17821     ],
17822     [
17823         "Cornish",
17824         "kernowek",
17825         "kw"
17826     ],
17827     [
17828         "Kyrgyz",
17829         "Кыргызча",
17830         "ky"
17831     ],
17832     [
17833         "Latin",
17834         "Latina",
17835         "la"
17836     ],
17837     [
17838         "Ladino",
17839         "Ladino",
17840         "lad"
17841     ],
17842     [
17843         "Luxembourgish",
17844         "Lëtzebuergesch",
17845         "lb"
17846     ],
17847     [
17848         "лакку",
17849         "лакку",
17850         "lbe"
17851     ],
17852     [
17853         "Lezghian",
17854         "лезги",
17855         "lez"
17856     ],
17857     [
17858         "Ganda",
17859         "Luganda",
17860         "lg"
17861     ],
17862     [
17863         "Limburgish",
17864         "Limburgs",
17865         "li"
17866     ],
17867     [
17868         "Ligurian",
17869         "Ligure",
17870         "lij"
17871     ],
17872     [
17873         "Lombard",
17874         "lumbaart",
17875         "lmo"
17876     ],
17877     [
17878         "Lingala",
17879         "lingála",
17880         "ln"
17881     ],
17882     [
17883         "Lao",
17884         "ລາວ",
17885         "lo"
17886     ],
17887     [
17888         "Northern Luri",
17889         "لۊری شومالی",
17890         "lrc"
17891     ],
17892     [
17893         "Lithuanian",
17894         "lietuvių",
17895         "lt"
17896     ],
17897     [
17898         "Latgalian",
17899         "latgaļu",
17900         "ltg"
17901     ],
17902     [
17903         "Latvian",
17904         "latviešu",
17905         "lv"
17906     ],
17907     [
17908         "Maithili",
17909         "मैथिली",
17910         "mai"
17911     ],
17912     [
17913         "Basa Banyumasan",
17914         "Basa Banyumasan",
17915         "map-bms"
17916     ],
17917     [
17918         "Moksha",
17919         "мокшень",
17920         "mdf"
17921     ],
17922     [
17923         "Malagasy",
17924         "Malagasy",
17925         "mg"
17926     ],
17927     [
17928         "Eastern Mari",
17929         "олык марий",
17930         "mhr"
17931     ],
17932     [
17933         "Maori",
17934         "Māori",
17935         "mi"
17936     ],
17937     [
17938         "Minangkabau",
17939         "Baso Minangkabau",
17940         "min"
17941     ],
17942     [
17943         "Macedonian",
17944         "македонски",
17945         "mk"
17946     ],
17947     [
17948         "Malayalam",
17949         "മലയാളം",
17950         "ml"
17951     ],
17952     [
17953         "Mongolian",
17954         "монгол",
17955         "mn"
17956     ],
17957     [
17958         "Marathi",
17959         "मराठी",
17960         "mr"
17961     ],
17962     [
17963         "Western Mari",
17964         "кырык мары",
17965         "mrj"
17966     ],
17967     [
17968         "Malay",
17969         "Bahasa Melayu",
17970         "ms"
17971     ],
17972     [
17973         "Maltese",
17974         "Malti",
17975         "mt"
17976     ],
17977     [
17978         "Mirandese",
17979         "Mirandés",
17980         "mwl"
17981     ],
17982     [
17983         "Burmese",
17984         "မြန်မာဘာသာ",
17985         "my"
17986     ],
17987     [
17988         "Erzya",
17989         "эрзянь",
17990         "myv"
17991     ],
17992     [
17993         "Mazanderani",
17994         "مازِرونی",
17995         "mzn"
17996     ],
17997     [
17998         "Nauru",
17999         "Dorerin Naoero",
18000         "na"
18001     ],
18002     [
18003         "Nāhuatl",
18004         "Nāhuatl",
18005         "nah"
18006     ],
18007     [
18008         "Neapolitan",
18009         "Napulitano",
18010         "nap"
18011     ],
18012     [
18013         "Low German",
18014         "Plattdüütsch",
18015         "nds"
18016     ],
18017     [
18018         "Low Saxon",
18019         "Nedersaksies",
18020         "nds-nl"
18021     ],
18022     [
18023         "Nepali",
18024         "नेपाली",
18025         "ne"
18026     ],
18027     [
18028         "Newari",
18029         "नेपाल भाषा",
18030         "new"
18031     ],
18032     [
18033         "Dutch",
18034         "Nederlands",
18035         "nl"
18036     ],
18037     [
18038         "Norwegian Nynorsk",
18039         "norsk nynorsk",
18040         "nn"
18041     ],
18042     [
18043         "Norwegian",
18044         "norsk bokmål",
18045         "no"
18046     ],
18047     [
18048         "Novial",
18049         "Novial",
18050         "nov"
18051     ],
18052     [
18053         "Nouormand",
18054         "Nouormand",
18055         "nrm"
18056     ],
18057     [
18058         "Northern Sotho",
18059         "Sesotho sa Leboa",
18060         "nso"
18061     ],
18062     [
18063         "Navajo",
18064         "Diné bizaad",
18065         "nv"
18066     ],
18067     [
18068         "Nyanja",
18069         "Chi-Chewa",
18070         "ny"
18071     ],
18072     [
18073         "Occitan",
18074         "occitan",
18075         "oc"
18076     ],
18077     [
18078         "Livvi-Karelian",
18079         "Livvinкarjala",
18080         "olo"
18081     ],
18082     [
18083         "Oromo",
18084         "Oromoo",
18085         "om"
18086     ],
18087     [
18088         "Oriya",
18089         "ଓଡ଼ିଆ",
18090         "or"
18091     ],
18092     [
18093         "Ossetic",
18094         "Ирон",
18095         "os"
18096     ],
18097     [
18098         "Punjabi",
18099         "ਪੰਜਾਬੀ",
18100         "pa"
18101     ],
18102     [
18103         "Pangasinan",
18104         "Pangasinan",
18105         "pag"
18106     ],
18107     [
18108         "Pampanga",
18109         "Kapampangan",
18110         "pam"
18111     ],
18112     [
18113         "Papiamento",
18114         "Papiamentu",
18115         "pap"
18116     ],
18117     [
18118         "Picard",
18119         "Picard",
18120         "pcd"
18121     ],
18122     [
18123         "Pennsylvania German",
18124         "Deitsch",
18125         "pdc"
18126     ],
18127     [
18128         "Palatine German",
18129         "Pälzisch",
18130         "pfl"
18131     ],
18132     [
18133         "Pali",
18134         "पालि",
18135         "pi"
18136     ],
18137     [
18138         "Norfuk / Pitkern",
18139         "Norfuk / Pitkern",
18140         "pih"
18141     ],
18142     [
18143         "Polish",
18144         "polski",
18145         "pl"
18146     ],
18147     [
18148         "Piedmontese",
18149         "Piemontèis",
18150         "pms"
18151     ],
18152     [
18153         "Western Punjabi",
18154         "پنجابی",
18155         "pnb"
18156     ],
18157     [
18158         "Pontic",
18159         "Ποντιακά",
18160         "pnt"
18161     ],
18162     [
18163         "Pashto",
18164         "پښتو",
18165         "ps"
18166     ],
18167     [
18168         "Portuguese",
18169         "português",
18170         "pt"
18171     ],
18172     [
18173         "Quechua",
18174         "Runa Simi",
18175         "qu"
18176     ],
18177     [
18178         "Romansh",
18179         "rumantsch",
18180         "rm"
18181     ],
18182     [
18183         "Romani",
18184         "Romani",
18185         "rmy"
18186     ],
18187     [
18188         "Rundi",
18189         "Kirundi",
18190         "rn"
18191     ],
18192     [
18193         "Romanian",
18194         "română",
18195         "ro"
18196     ],
18197     [
18198         "Aromanian",
18199         "armãneashti",
18200         "roa-rup"
18201     ],
18202     [
18203         "tarandíne",
18204         "tarandíne",
18205         "roa-tara"
18206     ],
18207     [
18208         "Russian",
18209         "русский",
18210         "ru"
18211     ],
18212     [
18213         "Rusyn",
18214         "русиньскый",
18215         "rue"
18216     ],
18217     [
18218         "Kinyarwanda",
18219         "Kinyarwanda",
18220         "rw"
18221     ],
18222     [
18223         "Sanskrit",
18224         "संस्कृतम्",
18225         "sa"
18226     ],
18227     [
18228         "Sakha",
18229         "саха тыла",
18230         "sah"
18231     ],
18232     [
18233         "Sardinian",
18234         "sardu",
18235         "sc"
18236     ],
18237     [
18238         "Sicilian",
18239         "sicilianu",
18240         "scn"
18241     ],
18242     [
18243         "Scots",
18244         "Scots",
18245         "sco"
18246     ],
18247     [
18248         "Sindhi",
18249         "سنڌي",
18250         "sd"
18251     ],
18252     [
18253         "Northern Sami",
18254         "sámegiella",
18255         "se"
18256     ],
18257     [
18258         "Sango",
18259         "Sängö",
18260         "sg"
18261     ],
18262     [
18263         "Serbo-Croatian",
18264         "srpskohrvatski / српскохрватски",
18265         "sh"
18266     ],
18267     [
18268         "Sinhala",
18269         "සිංහල",
18270         "si"
18271     ],
18272     [
18273         "Simple English",
18274         "Simple English",
18275         "simple"
18276     ],
18277     [
18278         "Slovak",
18279         "slovenčina",
18280         "sk"
18281     ],
18282     [
18283         "Slovenian",
18284         "slovenščina",
18285         "sl"
18286     ],
18287     [
18288         "Samoan",
18289         "Gagana Samoa",
18290         "sm"
18291     ],
18292     [
18293         "Shona",
18294         "chiShona",
18295         "sn"
18296     ],
18297     [
18298         "Somali",
18299         "Soomaaliga",
18300         "so"
18301     ],
18302     [
18303         "Albanian",
18304         "shqip",
18305         "sq"
18306     ],
18307     [
18308         "Serbian",
18309         "српски / srpski",
18310         "sr"
18311     ],
18312     [
18313         "Sranan Tongo",
18314         "Sranantongo",
18315         "srn"
18316     ],
18317     [
18318         "Swati",
18319         "SiSwati",
18320         "ss"
18321     ],
18322     [
18323         "Southern Sotho",
18324         "Sesotho",
18325         "st"
18326     ],
18327     [
18328         "Saterland Frisian",
18329         "Seeltersk",
18330         "stq"
18331     ],
18332     [
18333         "Sundanese",
18334         "Basa Sunda",
18335         "su"
18336     ],
18337     [
18338         "Swedish",
18339         "svenska",
18340         "sv"
18341     ],
18342     [
18343         "Swahili",
18344         "Kiswahili",
18345         "sw"
18346     ],
18347     [
18348         "Silesian",
18349         "ślůnski",
18350         "szl"
18351     ],
18352     [
18353         "Tamil",
18354         "தமிழ்",
18355         "ta"
18356     ],
18357     [
18358         "Tulu",
18359         "ತುಳು",
18360         "tcy"
18361     ],
18362     [
18363         "Telugu",
18364         "తెలుగు",
18365         "te"
18366     ],
18367     [
18368         "Tetum",
18369         "tetun",
18370         "tet"
18371     ],
18372     [
18373         "Tajik",
18374         "тоҷикӣ",
18375         "tg"
18376     ],
18377     [
18378         "Thai",
18379         "ไทย",
18380         "th"
18381     ],
18382     [
18383         "Tigrinya",
18384         "ትግርኛ",
18385         "ti"
18386     ],
18387     [
18388         "Turkmen",
18389         "Türkmençe",
18390         "tk"
18391     ],
18392     [
18393         "Tagalog",
18394         "Tagalog",
18395         "tl"
18396     ],
18397     [
18398         "Tswana",
18399         "Setswana",
18400         "tn"
18401     ],
18402     [
18403         "Tongan",
18404         "lea faka-Tonga",
18405         "to"
18406     ],
18407     [
18408         "Tok Pisin",
18409         "Tok Pisin",
18410         "tpi"
18411     ],
18412     [
18413         "Turkish",
18414         "Türkçe",
18415         "tr"
18416     ],
18417     [
18418         "Tsonga",
18419         "Xitsonga",
18420         "ts"
18421     ],
18422     [
18423         "Tatar",
18424         "татарча/tatarça",
18425         "tt"
18426     ],
18427     [
18428         "Tumbuka",
18429         "chiTumbuka",
18430         "tum"
18431     ],
18432     [
18433         "Twi",
18434         "Twi",
18435         "tw"
18436     ],
18437     [
18438         "Tahitian",
18439         "reo tahiti",
18440         "ty"
18441     ],
18442     [
18443         "Tuvinian",
18444         "тыва дыл",
18445         "tyv"
18446     ],
18447     [
18448         "Udmurt",
18449         "удмурт",
18450         "udm"
18451     ],
18452     [
18453         "Uyghur",
18454         "ئۇيغۇرچە / Uyghurche",
18455         "ug"
18456     ],
18457     [
18458         "Ukrainian",
18459         "українська",
18460         "uk"
18461     ],
18462     [
18463         "Urdu",
18464         "اردو",
18465         "ur"
18466     ],
18467     [
18468         "Uzbek",
18469         "oʻzbekcha/ўзбекча",
18470         "uz"
18471     ],
18472     [
18473         "Venda",
18474         "Tshivenda",
18475         "ve"
18476     ],
18477     [
18478         "Venetian",
18479         "vèneto",
18480         "vec"
18481     ],
18482     [
18483         "Veps",
18484         "vepsän kel’",
18485         "vep"
18486     ],
18487     [
18488         "Vietnamese",
18489         "Tiếng Việt",
18490         "vi"
18491     ],
18492     [
18493         "West Flemish",
18494         "West-Vlams",
18495         "vls"
18496     ],
18497     [
18498         "Volapük",
18499         "Volapük",
18500         "vo"
18501     ],
18502     [
18503         "Walloon",
18504         "walon",
18505         "wa"
18506     ],
18507     [
18508         "Waray",
18509         "Winaray",
18510         "war"
18511     ],
18512     [
18513         "Wolof",
18514         "Wolof",
18515         "wo"
18516     ],
18517     [
18518         "Wu Chinese",
18519         "吴语",
18520         "wuu"
18521     ],
18522     [
18523         "Kalmyk",
18524         "хальмг",
18525         "xal"
18526     ],
18527     [
18528         "Xhosa",
18529         "isiXhosa",
18530         "xh"
18531     ],
18532     [
18533         "Mingrelian",
18534         "მარგალური",
18535         "xmf"
18536     ],
18537     [
18538         "Yiddish",
18539         "ייִדיש",
18540         "yi"
18541     ],
18542     [
18543         "Yoruba",
18544         "Yorùbá",
18545         "yo"
18546     ],
18547     [
18548         "Zhuang",
18549         "Vahcuengh",
18550         "za"
18551     ],
18552     [
18553         "Zeelandic",
18554         "Zeêuws",
18555         "zea"
18556     ],
18557     [
18558         "Chinese",
18559         "中文",
18560         "zh"
18561     ],
18562     [
18563         "Classical Chinese",
18564         "文言",
18565         "zh-classical"
18566     ],
18567     [
18568         "Chinese (Min Nan)",
18569         "Bân-lâm-gú",
18570         "zh-min-nan"
18571     ],
18572     [
18573         "Cantonese",
18574         "粵語",
18575         "zh-yue"
18576     ],
18577     [
18578         "Zulu",
18579         "isiZulu",
18580         "zu"
18581     ]
18582 ];
18583
18584 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}}};
18585 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}}};
18586 var dataSuggestions = {
18587         amenity: amenity,
18588         shop: shop
18589 };
18590
18591 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"]]},{"countryCodes":["jp"],"format":[["postcode","province","county"],["city","suburb"],["quarter","neighbourhood"],["block_number","housenumber"]],"dropdowns":["postcode","province","county","city","suburb","quarter","neighbourhood","block_number"],"widths":{"postcode":0.3,"province":0.35,"county":0.35,"city":0.65,"suburb":0.35,"quarter":0.5,"neighbourhood":0.5,"block_number":0.5,"housenumber":0.5}},{"countryCodes":["tr"],"format":[["neighbourhood"],["street","housenumber"],["postcode","district","city"]]}];
18592
18593 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"}}];
18594
18595 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"];
18596
18597 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},"mk":{"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}};
18598
18599 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","ie":"+353 20 912 3456","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 1632 961234","gg":"+44 1632 961234","im":"+44 1632 961234","je":"+44 1632 961234","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 1234 5678","tw":"+886 1 2345 6789","tr":"+90 312 123 4567"};
18600
18601 var type = "FeatureCollection";
18602 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]]]}}];
18603 var dataImperial = {
18604         type: type,
18605         features: features
18606 };
18607
18608 var type$1 = "FeatureCollection";
18609 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]]]}}];
18610 var dataDriveLeft = {
18611         type: type$1,
18612         features: features$1
18613 };
18614
18615 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":{"single":"Delete this feature permanently.","multiple":"Delete these features 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} features."},"incomplete_relation":{"single":"This feature can't be deleted because it hasn't been fully downloaded.","multiple":"These features can't be deleted because they haven't been fully downloaded."},"part_of_relation":{"single":"This feature can't be deleted because it is part of a larger relation. You must remove it from the relation first.","multiple":"These features can't be deleted because they are part of larger relations. You must remove them from the relations first."},"connected_to_hidden":{"single":"This feature can't be deleted because it is connected to a hidden feature.","multiple":"These features can't be deleted because some are connected to hidden features."}},"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":{"single":"Move this feature to a different location.","multiple":"Move these features 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 features."},"incomplete_relation":{"single":"This feature can't be moved because it hasn't been fully downloaded.","multiple":"These features can't be moved because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be moved because not enough of it is currently visible.","multiple":"These features can't be moved because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be moved because it is connected to a hidden feature.","multiple":"These features can't be moved because some are connected to hidden features."}},"reflect":{"title":"reflect","description":{"long":{"single":"Reflect this feature across its long axis.","multiple":"Reflect these features across their long axis."},"short":{"single":"Reflect this feature across its short axis.","multiple":"Reflect these features across their short axis."}},"key":{"long":"T","short":"Y"},"annotation":{"long":{"single":"Reflected an feature across its long axis.","multiple":"Reflected multiple features across their long axis."},"short":{"single":"Reflected an feature across its short axis.","multiple":"Reflected multiple features across their short axis."}},"incomplete_relation":{"single":"This feature can't be reflected because it hasn't been fully downloaded.","multiple":"These features can't be reflected because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be reflected because not enough of it is currently visible.","multiple":"These features can't be reflected because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be reflected because it is connected to a hidden feature.","multiple":"These features can't be reflected because some are connected to hidden features."}},"rotate":{"title":"Rotate","description":{"single":"Rotate this feature around its center point.","multiple":"Rotate these features around their center point."},"key":"R","annotation":{"line":"Rotated a line.","area":"Rotated an area.","multiple":"Rotated multiple features."},"incomplete_relation":{"single":"This feature can't be rotated because it hasn't been fully downloaded.","multiple":"These features can't be rotated because they haven't been fully downloaded."},"too_large":{"single":"This feature can't be rotated because not enough of it is currently visible.","multiple":"These features can't be rotated because not enough of them are currently visible."},"connected_to_hidden":{"single":"This feature can't be rotated because it is connected to a hidden feature.","multiple":"These features can't be rotated because some are connected to hidden features."}},"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":"Upload to OpenStreetMap","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":"Upload","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 features","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":"Review your changes and upload them 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 feature 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 feature has been deleted by {user}.","location":"This feature 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":{"disconnected_highway":"Disconnected highway","disconnected_highway_tooltip":"Roads should be connected to other roads.","untagged_point":"Untagged point","untagged_line":"Untagged line","untagged_area":"Untagged area","untagged_relation":"Untagged relation","many_deletions":"You're deleting {n} features. 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.","untagged_relation_tooltip":"Select a feature type that describes what this relation 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 file","drag_drop":"Drag and drop a .gpx, .geojson or .kml file on the page, or click the button to the right to browse","zoom":"Zoom to layer","browse":"Browse for a 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-natural-area":{"name":"Natural Features"},"category-natural-line":{"name":"Natural Features"},"category-natural-point":{"name":"Natural 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":{"block_number":"Block Number","block_number!jp":"Block No.","city":"City","city!jp":"City/Town/Village/Tokyo Special Ward","city!vn":"City/Town","conscriptionnumber":"123","country":"Country","county":"County","county!jp":"District","district":"District","district!vn":"Arrondissement/Town/District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","housenumber!jp":"Building No./Lot No.","neighbourhood":"Neighbourhood","neighbourhood!jp":"Chōme/Aza/Koaza","place":"Place","postcode":"Postcode","province":"Province","province!jp":"Prefecture","quarter":"Quarter","quarter!jp":"Ōaza/Machi","state":"State","street":"Street","subdistrict":"Subdistrict","subdistrict!vn":"Ward/Commune/Townlet","suburb":"Suburb","suburb!jp":"Ward"}},"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"},"bunker_type":{"label":"Type"},"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"}},"castle_type":{"label":"Type"},"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"},"email":{"label":"Email","placeholder":"example@example.com"},"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/position":{"label":"Position","options":{"lane":"Lane","parking_lot":"Parking Lot","sidewalk":"Sidewalk","green":"Green"}},"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"},"plant":{"label":"Plant"},"population":{"label":"Population"},"power_supply":{"label":"Power Supply"},"power":{"label":"Type"},"produce":{"label":"Produce"},"product":{"label":"Product"},"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"},"social_facility":{"label":"Type"},"source":{"label":"Source"},"sport_ice":{"label":"Sport"},"sport_racing":{"label":"Sport"},"sport":{"label":"Sport"},"stars":{"label":"Stars"},"step_count":{"label":"Number of Steps"},"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"}},"toll":{"label":"Toll"},"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/drag_lift":{"name":"Drag Lift","terms":""},"aerialway/gondola":{"name":"Gondola","terms":""},"aerialway/goods":{"name":"Goods Aerialway","terms":""},"aerialway/magic_carpet":{"name":"Magic Carpet Lift","terms":""},"aerialway/mixed_lift":{"name":"Mixed 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/coworking_space":{"name":"Coworking Space","terms":""},"amenity/nursing_home":{"name":"Nursing Home","terms":""},"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/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,infirmary,institution,sanatorium,sanitarium,sick,surgery,ward"},"amenity/hunting_stand":{"name":"Hunting Stand","terms":"game,gun,lookout,rifle,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/social_facility/nursing_home":{"name":"Nursing Home","terms":"elderly,living,nursing,old,senior"},"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/border_control":{"name":"Border Control","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":"fire plug"},"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":"autobahn,expressway,freeway,highway,interstate,parkway,thruway,turnpike"},"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/aquaculture":{"name":"Aquaculture","terms":"fish farm,crustacean,algae,aquafarming,shrimp farm,oyster farm,mariculture,algaculture"},"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":"crop,grow,plant"},"landuse/farmyard":{"name":"Farmyard","terms":"crop,grow,plant"},"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/military/airfield":{"name":"Military Airfield","terms":"air force,army,base,bomb,fight,force,guard,heli*,jet,marine,navy,plane,troop,war"},"landuse/military/barracks":{"name":"Barracks","terms":"air force,army,base,fight,force,guard,marine,navy,troop,war"},"landuse/military/bunker":{"name":"Military Bunker","terms":"air force,army,base,fight,force,guard,marine,navy,troop,war"},"landuse/military/checkpoint":{"name":"Checkpoint","terms":"air force,army,base,force,guard,marine,navy,troop,war"},"landuse/military/danger_area":{"name":"Danger Area","terms":"air force,army,base,blast,bomb,explo*,force,guard,mine,marine,navy,troop,war"},"landuse/military/naval_base":{"name":"Naval Base","terms":"base,fight,force,guard,marine,navy,ship,sub,troop,war"},"landuse/military/nuclear_explosion_site":{"name":"Nuclear Explosion Site","terms":"atom,blast,bomb,detonat*,nuke,site,test"},"landuse/military/obstacle_course":{"name":"Obstacle Course","terms":"army,base,force,guard,marine,navy,troop,war"},"landuse/military/office":{"name":"Military Office","terms":"air force,army,base,enlist,fight,force,guard,marine,navy,recruit,troop,war"},"landuse/military/range":{"name":"Military Range","terms":"air force,army,base,fight,fire,force,guard,gun,marine,navy,rifle,shoot*,snip*,train,troop,war"},"landuse/military/training_area":{"name":"Training Area","terms":"air force,army,base,fight,fire,force,guard,gun,marine,navy,rifle,shoot*,snip*,train,troop,war"},"landuse/orchard":{"name":"Orchard","terms":"fruit"},"landuse/plant_nursery":{"name":"Plant Nursery","terms":"flower,garden,grow,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":"grape,wine"},"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/horse_riding":{"name":"Horseback Riding Facility","terms":"equestrian,stable"},"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":"Factory","terms":"assembly,build,brewery,car,plant,plastic,processing,manufacture,refinery"},"natural":{"name":"Natural","terms":""},"natural/bare_rock":{"name":"Bare Rock","terms":"rock"},"natural/bay":{"name":"Bay","terms":""},"natural/beach":{"name":"Beach","terms":"shore"},"natural/cave_entrance":{"name":"Cave Entrance","terms":"cavern,hollow,grotto,shelter,cavity"},"natural/cliff":{"name":"Cliff","terms":"escarpment"},"natural/coastline":{"name":"Coastline","terms":"shore"},"natural/fell":{"name":"Fell","terms":""},"natural/glacier":{"name":"Glacier","terms":""},"natural/grassland":{"name":"Grassland","terms":"prairie,savanna"},"natural/heath":{"name":"Heath","terms":""},"natural/peak":{"name":"Peak","terms":"acme,aiguille,alp,climax,crest,crown,hill,mount,mountain,pinnacle,summit,tip,top"},"natural/ridge":{"name":"Ridge","terms":"crest"},"natural/saddle":{"name":"Saddle","terms":"pass,mountain pass,top"},"natural/sand":{"name":"Sand","terms":"desert"},"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"},"noexit/yes":{"name":"No Exit","terms":"no exit,road end,dead end"},"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/coworking":{"name":"Coworking Space","terms":"coworking,office"},"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/lawyer/notary":{"name":"Notary Office","terms":"clerk,signature,wills,deeds,estate"},"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/square":{"name":"Square","terms":""},"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/plant":{"name":"Power Station Grounds","terms":"coal,gas,generat*,hydro,nuclear,power,station"},"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/watches":{"name":"Watches Shop","terms":""},"shop/water_sports":{"name":"Watersport/Swim Shop","terms":""},"shop/weapons":{"name":"Weapon Shop","terms":"ammo,gun,knife,knives"},"shop/window_blind":{"name":"Window Blind Store","terms":""},"shop/wine":{"name":"Wine Shop","terms":""},"tourism":{"name":"Tourism","terms":""},"tourism/alpine_hut":{"name":"Alpine Hut","terms":""},"tourism/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":""}}}};
18616
18617 var dataImagery = [{"id":"sjcgis.org-Aerials_2013_WM","name":"2013 aerial imagery for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2013_WM/MapServer/tile/{zoom}/{y}/{x}","description":"Public domain aerial imagery taken in May/June 2013 from San Juan County, WA. Resolution is 9 inch.","scaleExtent":[0,19],"polygon":[[[-123.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]],[[-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]]],"best":true},{"id":"OS7","name":"7th Series (OS7)","type":"tms","template":"http://ooc.openstreetmap.org/os7/{zoom}/{x}/{y}.jpg","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]]]},{"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":"lu.geoportail.opendata.basemap","name":"Basemap geoportail.lu","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":"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],[2.31953818544,6.55745092536]],[[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],[1.69563043958,6.25076170066]]],"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":"lu.geoportail.opendata.cadastre","name":"Cadastre geoportail.lu","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":"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],[15.0063684,49.0177392]]],"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],[15.0063684,49.0177392]]],"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-S2A_R119_N09_20160327T050917","name":"imagico.de OSM images for mapping: Adams Bridge","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R119_N09_20160327T050917&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160330T091608_R119_V20160327T050917_20160327T050917, 2016-03-27, channels 234 (true color), Supplementing incomplete coverage in other sources","scaleExtent":[0,14],"polygon":[[[79.01779174804685,8.827572266651268],[79.01401519775389,9.64678471986339],[80.17642021179198,9.650423231331946],[80.17727851867674,8.831304063493132],[79.01779174804685,8.827572266651268]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC80700162014211LGN00","name":"imagico.de OSM images for mapping: 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.70872943147867,62.30357443926811],[-152.70838610872474,62.58153176976553],[-152.00835101350992,63.54645538851267],[-148.99432055696695,63.53329945446586],[-148.99432055696695,62.30357443926811],[-152.70872943147867,62.30357443926811]]],"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":[[[114.35999506049737,2.028456548619032],[113.5344754987298,2.030000532161949],[113.53619211249934,3.070767124420059],[114.76511591010677,3.067510236472651],[114.76254098945248,2.088156161702156],[114.35999506049737,2.028456548619032]]],"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 to 2016, channels 234 (true color), Missing Islands in OSM","scaleExtent":[0,13],"polygon":[[[104.00154570197358,-0.000078769115171],[104.00137404059662,1.45099139170518],[104.91014937018647,1.451162998032411],[104.91014937018647,-0.000078769115171],[104.00154570197358,-0.000078769115171]]],"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.246529403113632,-54.47046993167111],[3.246529403113632,-54.375391687979096],[3.463852706336288,-54.375391687979096],[3.463852706336288,-54.47046993167111],[3.246529403113632,-54.47046993167111]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","best":true},{"id":"osmim-imagicode-S2A_R065_N47_20160929T102022","name":"imagico.de OSM images for mapping: Cental Alps in late September 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R065_N47_20160929T102022&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160929Txxxxxx_R065_V20160929T102022_20160929T102344, 2016-09-29, channels 234 (true color), Up-to-date image for glacier mapping - beware of some fresh snow at higher altitudes","scaleExtent":[0,13],"polygon":[[[10.559062957763668,45.95484945195885],[7.473964691162107,45.95532682303484],[7.555847167968747,46.27080015119853],[8.05469512939453,47.66469371011084],[11.752452850341793,47.664809318453564],[11.752452850341793,46.813336457338615],[11.38423919677734,45.955088138010865],[10.559062957763668,45.95484945195885]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-LC82050982015344LGN00","name":"imagico.de OSM images for mapping: 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":[[[-34.17701089820909,-55.29692751183208],[-35.19599283180284,-55.282851769908206],[-35.16663873634385,-54.7209735214882],[-34.12516916236925,-54.73465315976587],[-34.14010370216417,-55.29692751183208],[-34.17701089820909,-55.29692751183208]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-EO1A0040712016264110KF","name":"imagico.de OSM images for mapping: Coropuna","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A0040712016264110KF&z={zoom}&x={x}&y={-y}","description":"EO1A0040712016264110KF, 2016-09-21, channels 123 (true color), Up-to-date image for glacier mapping","scaleExtent":[0,14],"polygon":[[[-72.7594470977783,-15.68684010813036],[-72.7594470977783,-15.49570157136026],[-72.74434089660643,-15.426295586903299],[-72.41286277770995,-15.426295586903299],[-72.41286277770995,-15.652957427428944],[-72.42410659790038,-15.686674840407827],[-72.7594470977783,-15.68684010813036]]],"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.839749701876779,6.257803795151386],[1.839749701876779,7.114271792431897],[2.549397834200998,7.114271792431897],[2.549397834200998,6.489052510574106],[2.497813590426584,6.258059752887941],[1.839749701876779,6.257803795151386]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R040_N01_20160311T164128","name":"imagico.de OSM images for mapping: Darwin and Wolf islands, Galapagos","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R040_N01_20160311T164128&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160312T000419_R040_V20160311T164128_20160311T164128, 2016-03-11, channels 234 (true color), Recent image, only old and poor images in other sources currently","scaleExtent":[0,14],"polygon":[[[-92.05216379429558,1.321295617717369],[-92.05216379429558,1.72181118585353],[-91.74849481846549,1.72181118585353],[-91.74849481846549,1.321295617717369],[-92.05216379429558,1.321295617717369]]],"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.34798733886554,74.38945823827667],[-84.34798733886554,75.89030323920836],[-79.14870755370929,75.89030323920836],[-79.14870755370929,74.38945823827667],[-84.34798733886554,74.38945823827667]]],"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":[[[-13.047005598725303,64.2110895294821],[-15.164963667572959,64.22408122727819],[-15.168053572358117,64.81572800422087],[-13.043572371186242,64.80359943673454],[-13.047005598725303,64.2110895294821]]],"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.805085317123331],[-78.531997745432,-1.608105565001241],[-78.33561713019762,-1.608105565001241],[-78.33561713019762,-1.805085317123331],[-78.531997745432,-1.805085317123331]]],"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.13476090727487,-61.63471600102006],[-56.13476090727487,-61.199363166283845],[-55.83263688383738,-60.84015069906498],[-53.72343354521433,-60.83981613078141],[-53.72343354521433,-61.63471600102006],[-56.13476090727487,-61.63471600102006]]],"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.758781955967567,14.748140156641956],[-24.758781955967567,15.092493544965103],[-24.267057941685337,15.092493544965103],[-24.267057941685337,14.748140156641956],[-24.758781955967567,14.748140156641956]]],"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 to 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.5600891113281,76.43270387722659],[-74.5600891113281,82.6959093208192],[-12.86159673508746,82.6959093208192],[-11.878165975221727,82.54102593940235],[-10.7796478271484,82.51186682511671],[-10.7796478271484,78.34463154312763],[-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.06896521028185,-53.270590689700434],[73.06896521028185,-52.875489636268725],[73.67338491853381,-52.87673289134188],[74.08863378938341,-52.94950473139763],[74.08863378938341,-53.270590689700434],[73.06896521028185,-53.270590689700434]]],"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":[[[-69.85679747431641,-55.55949231551995],[-72.26520659296875,-55.149427383391455],[-72.26520659296875,-54.51089432315929],[-72.08530546992188,-54.17909103768387],[-69.49115874140625,-54.17889010631196],[-69.49150206416016,-55.28378528847367],[-69.62230803339844,-55.55910398108892],[-69.85679747431641,-55.55949231551995]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R021_N44_20160807T083013","name":"imagico.de OSM images for mapping: Kerch Strait","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R021_N44_20160807T083013&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160807T224006_R021_V20160807T083013_20160807T083013, 2016-08-07, channels 234 (true color), State of bridge construction in August 2016","scaleExtent":[0,14],"polygon":[[[35.932588577270494,44.96236872935039],[35.932588577270494,45.559256426515695],[37.369909286499016,45.559256426515695],[37.369909286499016,44.96236872935039],[35.932588577270494,44.96236872935039]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-ls_polar2","name":"imagico.de OSM images for mapping: Landsat off-nadir July 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ls_polar2&z={zoom}&x={x}&y={-y}","description":"LC80402432016199LGN00-LC80402482016199LGN00, 2016-07-17, channels 234 (true color), Latest images north of the regular Landsat limit","scaleExtent":[0,10],"polygon":[[[-79.05174500251786,81.91484289044183],[-79.05174500251786,83.43338556749623],[-73.60389956385866,83.80224987787145],[-26.424486898081835,83.80224987787145],[-21.492998879371186,83.50352415480617],[-16.888354121159868,83.15094632775453],[-16.888354121159868,81.91484289044183],[-79.05174500251786,81.91484289044183]]],"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.210747081406492,-56.72108048139938],[-28.210747081406492,-56.624975043089115],[-27.96956284678735,-56.624975043089115],[-27.96956284678735,-56.72108048139938],[-28.210747081406492,-56.72108048139938]]],"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":[[[-27.992928409215843,-56.73479060902333],[-28.227761172887714,-56.732624892496354],[-28.2241562839717,-56.600752537318456],[-27.969754123327167,-56.60283135691063],[-27.97318735086623,-56.73479060902333],[-27.992928409215843,-56.73479060902333]]],"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), First available image north of the regular Landsat limit, mostly with seasonal snow cover so difficult to interpret","scaleExtent":[0,10],"polygon":[[[-85.76109385682587,81.39333391115835],[-89.83015512094161,82.14951616258433],[-89.83152841195212,82.24404688557661],[-84.99342418195555,82.73098798225534],[-79.95207288240479,83.13107965605444],[-74.55641250214465,83.46266728201661],[-69.35850602739671,83.70450775086888],[-28.207840897721187,83.70450775086888],[-23.06623935440381,83.46532469372944],[-17.96583654140148,83.15518123848051],[-17.96720983241198,82.72386035102944],[-22.781968115230015,81.44190408358111],[-85.76109385682587,81.39333391115835]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R092_S02_20160613T075613","name":"imagico.de OSM images for mapping: Mount Kenya 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R092_S02_20160613T075613&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160613T140051_R092_V20160613T075613_20160613T075613, 2016-06-13, channels 234 (true color), Up-to-date image for glacier mapping","scaleExtent":[0,14],"polygon":[[[37.20665931701659,-0.266846645776291],[37.20665931701659,-0.011930465612033],[37.5655174255371,-0.011930465612033],[37.5655174255371,-0.266846645776291],[37.20665931701659,-0.266846645776291]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R092_S05_20160802T075556","name":"imagico.de OSM images for mapping: Mount Kilimanjaro 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R092_S05_20160802T075556&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160802T130554_R092_V20160802T075556_20160802T075556, 2016-08-02, channels 234 (true color), Up-to-date image for glacier mapping","scaleExtent":[0,14],"polygon":[[[37.24768638610839,-3.229213650135676],[37.24768638610839,-2.968155849006605],[37.61581420898436,-2.968155849006605],[37.61581420898436,-3.229213650135676],[37.24768638610839,-3.229213650135676]]],"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.38853376619625,-2.800534349432724],[150.38853376619625,-2.383396178206425],[150.83348005525875,-2.383396178206425],[150.83348005525875,-2.800534349432724],[150.38853376619625,-2.800534349432724]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-ural_s2_2016","name":"imagico.de OSM images for mapping: Northern and Polar Ural mountains August 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ural_s2_2016&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160812T212938_R092_V20160812T073612_20160812T073615/S2A_OPER_PRD_MSIL1C_PDMC_20160812T222950_R092_V20160812T073612_20160812T073615, 2016-08-12, channels 234 (true color), Up-to-date late summer imagery with few clouds - caution: not all visible snow is glaciers","scaleExtent":[0,13],"polygon":[[[59.198977223476454,64.8920468958533],[59.198977223476454,66.91656046303187],[60.733286610683486,68.44289182710118],[67.7329509173241,68.44327026354412],[67.7329509173241,67.748828729217],[64.21646761043934,64.9195663902952],[59.198977223476454,64.8920468958533]]],"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":[[[-81.62923243782096,82.45969864814401],[-83.03136255954291,82.47985512217643],[-83.03136255954291,83.05876272004272],[-72.80309111332822,83.09567468670448],[-65.65785798568925,83.03232446260982],[-65.8116665788654,82.45969864814401],[-81.62923243782096,82.45969864814401]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-nellesmere_ast_2016","name":"imagico.de OSM images for mapping: Northern Ellesmere Island July 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=nellesmere_ast_2016&z={zoom}&x={x}&y={-y}","description":"ASTER L1T, 2012-07-08 to 2012-07-15, channels 12x (true color with estimated blue), Assembled from July 2016 ASTER imagery","scaleExtent":[0,10],"polygon":[[[-78.89729497133754,82.17577067162792],[-82.64500613899595,82.19425721404356],[-82.64500613899595,83.08067098163464],[-66.58986093522367,83.08497116318647],[-63.78010752773773,82.98907949583335],[-63.78010752773773,82.72198178031782],[-65.0092029821365,82.17577067162792],[-78.89729497133754,82.17577067162792]]],"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.28027339774928],[7.63567991501593,53.66770140276793],[8.49433012253546,55.502457780526],[9.207754805152648,55.48106268908912],[9.207754805152648,53.28027339774928],[7.63567991501593,53.28027339774928]]],"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.28027339774928],[7.63567991501593,53.66810821588294],[8.49433012253546,55.502457780526],[9.207754805152648,55.48106268908912],[9.207754805152648,53.28027339774928],[7.63567991501593,53.28027339774928]]],"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.49221819430999,82.48971755550389],[-52.49221819430999,82.94294978186194],[-49.28695697579964,83.47311821807558],[-44.52850362441216,83.7321400994933],[-29.525299334683975,83.7321400994933],[-25.263977329098022,83.58271128961059],[-21.183929736898254,83.39775984253468],[-21.183929736898254,82.74312310369845],[-23.404541300879075,82.48971755550389],[-52.49221819430999,82.48971755550389]]],"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.22790413350113,-53.20333324999222],[73.22790413350113,-53.01072925838941],[73.2594898268605,-52.94943913810479],[73.78992348164566,-52.94943913810479],[73.78992348164566,-53.06048282358537],[73.71782570332533,-53.20333324999222],[73.22790413350113,-53.20333324999222]]],"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.01653561766223,8.848981570244637],[-80.01653561766223,9.41480707574399],[-79.46859250242785,9.41480707574399],[-79.46859250242785,8.848981570244637],[-80.01653561766223,8.848981570244637]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-EO1A0120532016364110KF","name":"imagico.de OSM images for mapping: Panama Canal - Pacific side","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A0120532016364110KF&z={zoom}&x={x}&y={-y}","description":"EO1A0120532016364110KF, 2016-12-30, channels 123 (true color), New locks with less clouds than in the Sentinel-2 image - make sure to check image alignment","scaleExtent":[0,14],"polygon":[[[-79.62538719177245,8.770827350748924],[-79.68684196472167,8.821974500616129],[-79.6866703033447,8.93705081902936],[-79.65362548828124,9.0929436313527],[-79.268159866333,9.0929436313527],[-79.32832717895505,8.770827350748924],[-79.62538719177245,8.770827350748924]]],"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":[[[-53.20921946177197,-84.12524693598144],[-60.615377881406225,-83.78609327915953],[-60.615377881406225,-82.29968785439104],[-48.72405102147429,-82.29987186164387],[-44.52178052933989,-82.43683433550413],[-44.51354078327688,-84.12524693598144],[-53.20921946177197,-84.12524693598144]]],"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.112325688609005,42.1531576323006],[19.08425905347717,43.08073531915633],[20.63298799634826,43.09602978090892],[20.637880345591427,42.167791043253985],[19.112325688609005,42.1531576323006]]],"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.238571767352376,68.79971882076842],[-51.243335370562825,68.85302612951142],[-51.151668195269856,68.85302612951142],[-51.14038145973519,68.80116208175376],[-51.238571767352376,68.79971882076842]]],"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.96839858817646,22.36264542957619],[67.86231185721942,22.38391650007107],[67.86231185721942,24.886930816927297],[71.48986007499286,24.886930816927297],[71.48986007499286,22.36264542957619],[67.96839858817646,22.36264542957619]]],"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":[[[23.808114560320394,41.584878805945024],[22.992379697039144,41.6019534981177],[23.011863263323328,42.29983747360261],[23.99402383156063,42.283393175568236],[23.965613873674886,41.584878805945024],[23.808114560320394,41.584878805945024]]],"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.766296776846374,0.206886934953159],[29.766296776846374,0.509176367154027],[30.034603509024116,0.509176367154027],[30.034603509024116,0.206886934953159],[29.766296776846374,0.206886934953159]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R078_N01_20160702T082522","name":"imagico.de OSM images for mapping: Rwenzori Mountains 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R078_N01_20160702T082522&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160702T132847_R078_V20160702T082522_20160702T082522, 2016-07-02, channels 234 (true color), Up-to-date image for glacier mapping","scaleExtent":[0,14],"polygon":[[[29.8051357269287,0.235862065771959],[29.8051357269287,0.467085433008179],[30.02503395080565,0.467085433008179],[30.02503395080565,0.235862065771959],[29.8051357269287,0.235862065771959]]],"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.4263452007858],[-180,-67.32544337276457],[-179.8247337341308,-67.3253771978419],[-179.8247337341308,-67.4263452007858],[-180,-67.4263452007858]]],"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.12874872458635,-53.72050213468143],[-42.14625818503558,-53.45782244664258],[-41.67573435080706,-53.445862233424414],[-41.6558216310805,-53.70871763480476],[-42.12874872458635,-53.72050213468143]]],"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.84382442048364,-3.595452324350203],[120.84382442048364,-3.159848173206955],[120.98184016755395,-2.514681686347053],[122.62618449738794,-2.514681686347053],[122.62618449738794,-3.002148034113534],[122.5007000308352,-3.595452324350203],[120.84382442048364,-3.595452324350203]]],"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":[[[156.96951345925345,-84.50097988272655],[154.50857596843485,-84.46255082580927],[154.50857596843485,-82.60681485793681],[175.46774337070775,-82.58504749645738],[177.00582930246938,-83.52806548607914],[177.00582930246938,-84.19262083779002],[171.93838547371908,-84.34632646581997],[166.83798266071676,-84.44370142483508],[161.67028858819987,-84.50045345467909],[156.96951345925345,-84.50097988272655]]],"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.93976917529807,76.51132557714853],[-68.93976917529807,76.54990046497333],[-68.76634826923117,76.55175699880375],[-68.50992908740743,76.55175699880375],[-68.50743999744161,76.51611959755911],[-68.67897262836203,76.51193618208278],[-68.93976917529807,76.51132557714853]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule2_2015.09.25","name":"imagico.de OSM images for mapping: Thule Airbase DMS low altitude overflight September 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule2_2015.09.25&z={zoom}&x={x}&y={-y}","description":"DMS 2015-09-25, true color, Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,17],"polygon":[[[-68.74291885235837,76.52635852412212],[-68.74446380475094,76.52840070669755],[-68.74806869366695,76.54938731810256],[-68.7461482320123,76.56016657973251],[-68.72275936940244,76.56022393334496],[-68.72017371991207,76.5577475347327],[-68.71853220799495,76.5292079974043],[-68.71977675297786,76.52636602351234],[-68.74291885235837,76.52635852412212]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule_2015.10.06","name":"imagico.de OSM images for mapping: Thule Airbase DMS overflight October 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule_2015.10.06&z={zoom}&x={x}&y={-y}","description":"DMS 2015-10-06, true color, Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,16],"polygon":[[[-68.81923965911197,76.52510098413808],[-68.82651380996036,76.54176603738404],[-68.77344898680974,76.5439032956252],[-68.7021022270136,76.54544610909097],[-68.59176687697696,76.54560088014632],[-68.59183124999333,76.52793072237704],[-68.65970186690618,76.52510098413808],[-68.81923965911197,76.52510098413808]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-dms_thule_2015.09.25","name":"imagico.de OSM images for mapping: Thule Airbase DMS overflight September 2015","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=dms_thule_2015.09.25&z={zoom}&x={x}&y={-y}","description":"DMS 2015-09-25, true color, Icebridge DMS aerial images from Thule Airbase - alignment might be poor","scaleExtent":[0,16],"polygon":[[[-68.7777130980429,76.50687742381471],[-68.77661875676482,76.57064446843503],[-68.68115357350676,76.57065443536027],[-68.67630413960784,76.55384487076157],[-68.67619685124725,76.5307435998188],[-68.6852305312094,76.50688243050337],[-68.7777130980429,76.50687742381471]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R094_N79_20160812T105622","name":"imagico.de OSM images for mapping: Ushakov Island August 2016","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R094_N79_20160812T105622&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160813T183324_R094_V20160812T105622_20160812T105622, 2016-08-12, channels 234 (true color), Up-to-date late summer imagery with few clouds","scaleExtent":[0,12],"polygon":[[[78.45885691499899,80.72643412860921],[78.45885691499899,80.9098976404357],[80.48892435884663,80.9098976404357],[80.48892435884663,80.72643412860921],[78.45885691499899,80.72643412860921]]],"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.0613810625655,-11.789228234021259],[153.0613810625655,-11.288690822294749],[153.10927458673538,-11.072292520575749],[154.41201277643268,-11.072292520575749],[154.41201277643268,-11.789228234021259],[153.0613810625655,-11.789228234021259]]],"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.51741123877955],[-72.8669610523419,-41.045274923011036],[-72.23181395761533,-41.045274923011036],[-71.87510161630674,-41.10829439141359],[-72.00007109872861,-41.51741123877955],[-72.8669610523419,-41.51741123877955]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping"},{"id":"osmim-imagicode-S2A_R089_N52_20160623T024048","name":"imagico.de OSM images for mapping: Vostochny Cosmodrome","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R089_N52_20160623T024048&z={zoom}&x={x}&y={-y}","description":"S2A_R089_N52_20160623T024048, 2016-06-23, channels 234 (true color), Recent image showing newest features","scaleExtent":[0,13],"polygon":[[[126.36143429881301,51.375528375017275],[126.34804471141064,52.33932231282816],[128.60762341624462,52.340895519845674],[128.6117432892915,51.375528375017275],[126.36143429881301,51.375528375017275]]],"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":[[[75.98364343730569,34.97850982318471],[73.96164407817483,35.36957188964085],[74.44281091777444,37.09391400468158],[76.50600900737405,36.7026732100855],[75.98364343730569,34.97850982318471]]],"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.18070648306262,-14.4978507264954],[-71.17976234548938,-13.710292880050797],[-70.5563740550841,-13.71262765059222],[-70.5563740550841,-14.4978507264954],[-71.18070648306262,-14.4978507264954]]],"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":"Basel-Landschaft-2015","name":"Kanton Basel-Landschaft 10cm (2015)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTBASELLANDSCHAFT2015/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[18,21],"polygon":[[[7.370281219482422,47.413684985326796],[7.357578277587891,47.41507892620101],[7.357921600341797,47.41827323486739],[7.353544235229492,47.4196089792119],[7.344875335693359,47.42402250214274],[7.339725494384765,47.42971307765559],[7.332687377929687,47.430235650685475],[7.32685089111328,47.4319194618196],[7.325280543317693,47.43489176778178],[7.33050406703179,47.44175856152086],[7.338990092194756,47.44109169292469],[7.344964876980962,47.43607806019703],[7.352656881264292,47.43435807026775],[7.38119797480828,47.432081698142134],[7.375988960266113,47.414309359238985],[7.378145456314087,47.41399717320828],[7.382040023803711,47.41330745332341],[7.388391494750976,47.41397539271845],[7.413708184603623,47.410929293287566],[7.420743520414262,47.411098781635985],[7.427483310496426,47.41448047082256],[7.438105529405026,47.412739349590474],[7.448396898794484,47.41507114537187],[7.455576414208223,47.42792319548619],[7.45061852232364,47.43534476535272],[7.437842682352891,47.446323188615104],[7.425422575234655,47.443283894442736],[7.420904049355535,47.44594415975335],[7.422417620777747,47.45071647996838],[7.428795928789581,47.45387944195848],[7.430028776685507,47.459491697398036],[7.445765194338128,47.46197276972992],[7.44717015944249,47.456958090215814],[7.456512189239691,47.44925575541638],[7.492356675875099,47.458972279610066],[7.530679075390223,47.46118857622267],[7.527445320030451,47.473906165741866],[7.536326693749955,47.48383279861684],[7.536231113003725,47.49105266753894],[7.532603895549507,47.490968962664795],[7.531789123586811,47.49739885661967],[7.520038351186771,47.49678264400428],[7.512226152318425,47.49891674929323],[7.509348758631863,47.508884893812876],[7.499082452238831,47.51627805213703],[7.497870355425969,47.52124757864722],[7.502278119030558,47.514906577969604],[7.517459288006065,47.51728104695845],[7.522200236749534,47.514091442409054],[7.530955756497733,47.52904526885427],[7.519353655277215,47.53471778813415],[7.510751927105658,47.528989768842564],[7.50229842095598,47.52840455858729],[7.4980383403841,47.536152181750076],[7.505454651706732,47.54438188661593],[7.516758242758337,47.545408295649786],[7.527317399933993,47.552778846515565],[7.554658254426867,47.564368052237306],[7.5645783501094,47.55703599040843],[7.561243624111692,47.55172275211291],[7.558752685660356,47.55235329499035],[7.555882119169953,47.54433555917895],[7.564785321950861,47.54568625396918],[7.587263056821628,47.54190064304111],[7.582688476068778,47.53246814131337],[7.589482524394103,47.5279230654027],[7.590248428005343,47.51978966346127],[7.594781326929009,47.51929395578897],[7.613780785019665,47.53925099543145],[7.622303281783164,47.53977428916004],[7.622854488041502,47.550040256825795],[7.617740918118178,47.554366555487356],[7.617617220103555,47.558648485827725],[7.632727781497729,47.5614887674157],[7.639973682410965,47.55816478484801],[7.648995462809379,47.548295861439875],[7.661308760240334,47.544832242956765],[7.665860164458853,47.53745814872834],[7.674674254363578,47.5337535789565],[7.694938989531916,47.532496041115465],[7.71346844906592,47.53978344629896],[7.715956243413761,47.53582195507857],[7.723622825374551,47.536754165368905],[7.727157067196862,47.53293048764033],[7.733221863174538,47.53275465944404],[7.737974130690588,47.52732498381306],[7.749022330706917,47.5249849998809],[7.757861753102653,47.52605097450287],[7.787633628417415,47.52011695778467],[7.790143521321244,47.51864117486466],[7.788870069574476,47.50682929074843],[7.792799480290271,47.500684271209245],[7.786625359342518,47.49312139201968],[7.798890147748131,47.49565149600841],[7.798162871694108,47.49939947973339],[7.799400121334925,47.497477088945935],[7.807418124234862,47.4971384859743],[7.814709929059118,47.504801278976316],[7.831976267472122,47.51473657456054],[7.833207588232065,47.53382387257594],[7.846527268275818,47.53266095290337],[7.852330295179702,47.53523506225097],[7.862569292788096,47.52692027402488],[7.86395674074442,47.519309183202445],[7.876658649367283,47.52269034821798],[7.87567113137545,47.51319304945735],[7.893993798731052,47.50605656803392],[7.904769180395594,47.49217505264052],[7.904821911502771,47.48490926161113],[7.93328835504665,47.48140776210853],[7.947015241408695,47.48488995686335],[7.940027875634228,47.462021295570224],[7.948854362289874,47.46377967418039],[7.957614193951437,47.45880646812721],[7.957849013566705,47.451279351685564],[7.946784554043733,47.44319336966537],[7.950032053627354,47.431716361052416],[7.96183169437885,47.421834282667845],[7.956570351591289,47.41968057428149],[7.955037646053525,47.415605646331336],[7.948388855309641,47.4162657867356],[7.934927870271696,47.41176694218953],[7.936722434714782,47.408057452805856],[7.932661510641391,47.40527495151619],[7.909737672400531,47.398520997340924],[7.890221593189976,47.407141074214024],[7.883331964118422,47.40609724771633],[7.883443085719068,47.4012049891245],[7.877702761222016,47.401257097623],[7.869136696167237,47.3955142728722],[7.879434713089799,47.38799354849815],[7.878812180597903,47.38351047538804],[7.862650230995195,47.38198499163919],[7.840119046365023,47.374763282921705],[7.830547227518145,47.36512144155488],[7.80216648325237,47.36109584064414],[7.796366151294341,47.3534705803715],[7.793560892325092,47.33905227137494],[7.78528803737905,47.3378822997136],[7.768963133383802,47.33891408469915],[7.766419194330703,47.342734660857005],[7.751518928544542,47.3443274446774],[7.734153146629586,47.35776074638933],[7.727913718160677,47.36885889855421],[7.701953574259492,47.37244716296033],[7.644203220263186,47.36720838530677],[7.641761060331779,47.38046937860509],[7.635580022356337,47.38059279713257],[7.633316986492583,47.38291397270416],[7.633305398225418,47.38533959871929],[7.637251158279386,47.38606854199808],[7.63272275093214,47.41003108104519],[7.664054730400831,47.41001995588381],[7.679802017668389,47.41751395224505],[7.686578998003315,47.43366406703297],[7.682972441800632,47.43872228466388],[7.684853783500164,47.447843589969715],[7.692273418589347,47.45421309996921],[7.698831030331891,47.45585888435835],[7.699930658071183,47.46190517358485],[7.709877972706822,47.469384739707586],[7.699760966314013,47.48063247960835],[7.668326578902932,47.48634665620256],[7.666120855554305,47.49686816039971],[7.65217109717027,47.49581439933043],[7.648646287658441,47.49183004211102],[7.655389581170213,47.49020559719241],[7.650513795302598,47.48826095607083],[7.655925875394832,47.48739459757455],[7.644422678687097,47.485637798180356],[7.640965961473804,47.482734093980326],[7.607299799570857,47.48939839412024],[7.608850381582776,47.48352506892989],[7.605631268762133,47.47935909729055],[7.608148977008936,47.475213682276376],[7.604494899927722,47.47044546774548],[7.618872436050056,47.4674530520825],[7.626072253389216,47.462913883669614],[7.62217338539308,47.46195224188912],[7.616464591762502,47.445234574416695],[7.615798850305441,47.432747890966844],[7.592069133423196,47.43271179535717],[7.581206884670679,47.42878068945942],[7.578423275099778,47.434906655087865],[7.568904367023134,47.43689695884281],[7.56829539909203,47.42233486107083],[7.58074128785892,47.414703988151935],[7.525235194936931,47.41163289737562],[7.531172340312734,47.40352507464003],[7.518616677418122,47.38822295597742],[7.511295677347134,47.38974369796625],[7.502255661148456,47.384806980223004],[7.492327480628366,47.385231761698726],[7.478410241257615,47.39055778320416],[7.47746817801916,47.401277162725364],[7.464484018734026,47.40251498235377],[7.460919593518167,47.40068414452088],[7.450020783333588,47.40392739156406],[7.44951323519806,47.39975827367453],[7.443401098004909,47.40231427489849],[7.441311347159463,47.40017886074712],[7.443566657511773,47.38890284041263],[7.437324174770898,47.3808884773088],[7.411692544769116,47.38057235919037],[7.416276198506335,47.384788794341716],[7.414494030814171,47.39429988358522],[7.398935569419335,47.39683906243558],[7.395920463999715,47.40338304393273],[7.388693876865087,47.403019088497395],[7.384054886906365,47.4123601395877],[7.379679679870605,47.4128137535428],[7.375844120979309,47.41401169352981],[7.370281219482422,47.413684985326796]]],"terms_url":"http://www.geo.bl.ch/fileadmin/user_upload/Geodaten/Nutzungsbedingungen_GBD_BL_V3p1.pdf","terms_text":"Geodaten des Kantons Basel-Landschaft 2015","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":[15,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":"londrina2011","name":"Londrina Ortofoto 2011","type":"tms","template":"https://siglon.londrina.pr.gov.br/arcgis/rest/services/Imagens/Ortofotos_2011_Paranacidade/MapServer/WMTS/tile/1.0.0/Imagens_Ortofotos_2011_Paranacidade/default/GoogleMapsCompatible/{zoom}/{y}/{x}","polygon":[[[-51.10903142008701,-23.392750890870328],[-51.110147219037096,-23.39111628244602],[-51.111981850003126,-23.389599820448623],[-51.11358044657587,-23.38976722295012],[-51.120999436701226,-23.38592675938185],[-51.12224934611127,-23.385109415587607],[-51.12483499560139,-23.383504255873166],[-51.12538216624037,-23.38186953335707],[-51.12482426676533,-23.37770385409619],[-51.12445948633935,-23.375054689723584],[-51.124373655650885,-23.372297138974446],[-51.12244246516032,-23.37032742475139],[-51.12302182230749,-23.366427304263887],[-51.128557901713755,-23.36548180323493],[-51.12832186732048,-23.358843408308623],[-51.12477062258506,-23.35475580404945],[-51.12703440699343,-23.35091432623551],[-51.12411616358548,-23.34679692655685],[-51.12025378260435,-23.347811512977742],[-51.1176466754421,-23.33969460448754],[-51.11264703783877,-23.341290443649072],[-51.109396200513004,-23.33488726938344],[-51.10756156954697,-23.334089313725826],[-51.10485790286019,-23.333980949007543],[-51.10252974543546,-23.334187827029368],[-51.09986899409291,-23.331015661953632],[-51.09801290545476,-23.329360589233605],[-51.09998701128955,-23.32830645478855],[-51.10322711977927,-23.325321337105603],[-51.10472915682748,-23.323193291476684],[-51.104664783811145,-23.321291814470847],[-51.10514758143378,-23.318444474199904],[-51.1063599399084,-23.3157547161216],[-51.10660670313775,-23.31467091543279],[-51.11050127062705,-23.311665785493048],[-51.111584883068964,-23.30842411016493],[-51.099504213666904,-23.309468549142686],[-51.09740136179941,-23.308631027972474],[-51.09511611971892,-23.307448636164267],[-51.09201548609798,-23.3049360186679],[-51.09036324534495,-23.3037141796735],[-51.09204767260616,-23.29874787986134],[-51.09269140276969,-23.297496421894902],[-51.09407542262125,-23.292953629109174],[-51.10073802981369,-23.293318240761657],[-51.10101697955121,-23.28870632248831],[-51.10068438563339,-23.28837126237015],[-51.10084531817427,-23.28777997775132],[-51.09937546763423,-23.28663682004102],[-51.09631774935752,-23.277914991984613],[-51.10285161051725,-23.273016720553397],[-51.10835550341534,-23.27033590016574],[-51.11309764895328,-23.268404099092194],[-51.13160489115448,-23.265338785827712],[-51.13188384089201,-23.262007272160396],[-51.1317336371872,-23.255058136908826],[-51.13290308031759,-23.254683563301587],[-51.132956724497895,-23.250750476893938],[-51.13473771128364,-23.2512729236245],[-51.13533852610292,-23.25133206840842],[-51.13516686472599,-23.24359373640034],[-51.13534925493897,-23.24117849627157],[-51.137516479822814,-23.24219388826517],[-51.13884685549409,-23.243495156026544],[-51.14108918223035,-23.24521044413634],[-51.1471724322756,-23.243179698340864],[-51.14761231455401,-23.23828015040167],[-51.149082165094036,-23.235884531292832],[-51.14976881060179,-23.236811236789336],[-51.15138886484666,-23.23853646924079],[-51.15289090189487,-23.238842079520833],[-51.15383503946804,-23.238950521710013],[-51.15820167574391,-23.238142132361276],[-51.16045473131624,-23.238161849232945],[-51.160347442955654,-23.24658068718069],[-51.15912435564498,-23.2478326235554],[-51.16131303820094,-23.247773477219496],[-51.166591625541805,-23.245939927797],[-51.17193458589902,-23.245821633420345],[-51.17205260309565,-23.249557713480034],[-51.174241285651625,-23.248404370116877],[-51.17514250788055,-23.2493211310392],[-51.176859121649926,-23.248157927934038],[-51.179466228812196,-23.251686936561047],[-51.18135450395853,-23.253806268366073],[-51.18273852381009,-23.253628837227893],[-51.18378994974384,-23.253264116924615],[-51.18495939287424,-23.253303546194683],[-51.18626831087339,-23.252150235227905],[-51.18665454897149,-23.247477745146526],[-51.191182117788244,-23.249143693933142],[-51.19141815218154,-23.252859966234126],[-51.19369266542598,-23.252781107419985],[-51.1938428691308,-23.26073575534214],[-51.20096681627374,-23.26054847664639],[-51.20126722368338,-23.24259807127726],[-51.209936123218775,-23.242775517090898],[-51.21090171846407,-23.26988252079656],[-51.21968863519614,-23.27221839365197],[-51.225965004290465,-23.2745345140599],[-51.22934458764894,-23.27860487489667],[-51.234515886629225,-23.28160089636689],[-51.23497722657975,-23.283246708422755],[-51.235073786104266,-23.285444377831148],[-51.23371122392482,-23.285897704227196],[-51.232155542696304,-23.28801649191402],[-51.22870085748543,-23.292293383844925],[-51.227402668322334,-23.294599300809004],[-51.22679112466699,-23.295476327114592],[-51.225600223864475,-23.29657013833941],[-51.22392652543933,-23.297210654251764],[-51.220482569064515,-23.30072850975029],[-51.21863720926242,-23.301300029310937],[-51.21668456109974,-23.30211788923888],[-51.21423838647836,-23.30441378240661],[-51.210966091480465,-23.306965823153238],[-51.22328279527583,-23.318296686707587],[-51.224387865389886,-23.31459209321986],[-51.22521398576639,-23.312887551432937],[-51.22511742624187,-23.312582111000477],[-51.22521398576639,-23.312513140483127],[-51.2255251220121,-23.312532846348883],[-51.22595427545445,-23.312385052284572],[-51.22616885217561,-23.31183328632629],[-51.22935531648505,-23.314887676277397],[-51.22802494081377,-23.31661189768144],[-51.227885465945,-23.31901591762422],[-51.22767088922384,-23.320227763653186],[-51.22723100694544,-23.321508564518947],[-51.2273919394863,-23.322227778055023],[-51.22725246461755,-23.322848466059934],[-51.230331640566384,-23.325577488448165],[-51.23046038659909,-23.326710459617892],[-51.229537706698046,-23.32789268010374],[-51.229162197436,-23.330503379743732],[-51.229290943468705,-23.33178408156439],[-51.22681258233914,-23.334473515196468],[-51.2260186484708,-23.336571826694826],[-51.22473118814376,-23.33839427691611],[-51.22210262330938,-23.340226553005806],[-51.22257469209598,-23.34196029634743],[-51.22380850824271,-23.343388647432523],[-51.22384069475089,-23.345309509145306],[-51.22440932306201,-23.347003784611864],[-51.2245380690947,-23.348294177581966],[-51.22404454263601,-23.34968305981433],[-51.22350810083308,-23.35010661675208],[-51.22381923707877,-23.35076657486812],[-51.22304676088255,-23.35174173085325],[-51.22259614976809,-23.35296312824164],[-51.22586844476598,-23.35480505304304],[-51.22650144609346,-23.36705763453823],[-51.22354028734128,-23.369145582171885],[-51.22366903337377,-23.37968330666716],[-51.220375280703756,-23.381633186264455],[-51.216469984378406,-23.38170212087667],[-51.21416328462579,-23.379949201028825],[-51.2092816642191,-23.37395167630701],[-51.20738266023672,-23.368141007697016],[-51.20628831895872,-23.36723491438801],[-51.20472190889416,-23.366269721227162],[-51.198230963078665,-23.366683376299132],[-51.19297383340994,-23.366506095711998],[-51.18986247095292,-23.3654424072124],[-51.18806002649507,-23.36464463523902],[-51.18718026193825,-23.3645264463904],[-51.18579624208668,-23.363738518041337],[-51.183038931219606,-23.36359078095478],[-51.18071077379488,-23.3637582163071],[-51.179069261877906,-23.361581540240305],[-51.177642326682125,-23.35836078207346],[-51.16683838877106,-23.356262814974126],[-51.166141014427254,-23.358538073547532],[-51.16475699457568,-23.360389770338585],[-51.16076586756186,-23.359217688669915],[-51.15983245882475,-23.36660458495632],[-51.162042599052846,-23.36861374957437],[-51.16276143106877,-23.374158492021696],[-51.158448438973174,-23.37580315788644],[-51.155047397942575,-23.376305417047273],[-51.15396378550066,-23.37903334042617],[-51.15298746141932,-23.381052164536694],[-51.15118501696147,-23.382076336717283],[-51.149167995782435,-23.382509637949354],[-51.14721534761976,-23.382155118864866],[-51.14517686876862,-23.382588419839323],[-51.14410398516276,-23.38376029492248],[-51.14512322458833,-23.388083341091015],[-51.141797285410156,-23.389402876058366],[-51.14030597719799,-23.38880219385971],[-51.14068148646006,-23.391608636504017],[-51.14127157244328,-23.393538646762796],[-51.14093897852546,-23.394434713394368],[-51.140456180902824,-23.39536031431835],[-51.13939402613302,-23.395104297688697],[-51.13738773379004,-23.393154616350518],[-51.13608954462695,-23.389796764546077],[-51.13428710016909,-23.389757375749994],[-51.132162790629465,-23.390072485790583],[-51.13172290835106,-23.39285920758337],[-51.12259266886514,-23.38864463742227],[-51.12228153261944,-23.391657871809155],[-51.11882684740854,-23.393174310244916],[-51.115683298443365,-23.393351555162592],[-51.10903142008701,-23.392750890870328]],[[-51.13829432042955,-23.41600741009485],[-51.133310776080314,-23.418665600378624],[-51.132087688769644,-23.416440600302334],[-51.13002238782791,-23.418291487939495],[-51.12868664773901,-23.419010176689888],[-51.12824140104259,-23.42102839134528],[-51.12696466955051,-23.421860280620358],[-51.12532852205271,-23.422692164660027],[-51.1244541219139,-23.420969322085504],[-51.1215144208339,-23.424109801147612],[-51.12063465627703,-23.423268081315832],[-51.11970661195797,-23.423120410617486],[-51.11977098497433,-23.42156985833077],[-51.1188000253111,-23.421545246243184],[-51.11643431696008,-23.420836416154565],[-51.11942766222045,-23.419167696990424],[-51.11787198099193,-23.416775337218567],[-51.116546969738685,-23.41730697646229],[-51.115699391690086,-23.415702207051474],[-51.115120034542905,-23.413088261827834],[-51.119078975048524,-23.411114231305813],[-51.119599323597356,-23.41169512115064],[-51.12052200349841,-23.41489489238112],[-51.12147686990764,-23.417139608782644],[-51.12308619531643,-23.418626220171642],[-51.12754939111684,-23.41653905242448],[-51.12803218873949,-23.417395582795194],[-51.13119719537679,-23.415574218468866],[-51.13080022844262,-23.414766903017576],[-51.13278506311348,-23.41264029239725],[-51.13521514448077,-23.411055157619415],[-51.13585887464424,-23.410956701416854],[-51.13682446988958,-23.411188073376714],[-51.137205343569626,-23.411576974270133],[-51.13730190309418,-23.41324086645236],[-51.137430649126884,-23.414707830961888],[-51.13829432042955,-23.41600741009485]],[[-51.18929065852,-23.61469318354],[-51.18868716149,-23.61385268133],[-51.18817754178,-23.61338573333],[-51.18731118826,-23.61301708899],[-51.18628926663,-23.61314488581],[-51.18401743559,-23.61395590119],[-51.18348904042,-23.61396573165],[-51.18183143525,-23.61283522407],[-51.18140496401,-23.61344471632],[-51.18062980561,-23.61313505529],[-51.18001021533,-23.61409352754],[-51.17865838198,-23.61328742827],[-51.18064589886,-23.61060367181],[-51.17972321896,-23.61018095058],[-51.18061639456,-23.60849005203],[-51.1821157494,-23.60850479833],[-51.18260927586,-23.60775273479],[-51.18319936184,-23.60804274673],[-51.18415154605,-23.60627808786],[-51.18511177687,-23.60666149766],[-51.18649043231,-23.60469528171],[-51.18902243762,-23.60610112912],[-51.18821241049,-23.60741848294],[-51.18918873458,-23.60801816947],[-51.188899056,-23.60953211999],[-51.18962325244,-23.60992535103],[-51.1911896625,-23.6111935131],[-51.1901489654,-23.61244691705],[-51.19054056792,-23.6127565797],[-51.19029380469,-23.61377895281],[-51.18929065852,-23.61469318354]],[[-51.08005769639,-23.52984412096],[-51.07962317853,-23.52205317842],[-51.08468182473,-23.52194496764],[-51.08581908135,-23.52404030606],[-51.0858941832,-23.52703569673],[-51.08579494147,-23.52777346722],[-51.08530141501,-23.52806365581],[-51.08513511805,-23.52856533627],[-51.08512438922,-23.52981952906],[-51.08470864682,-23.53023759067],[-51.08343459754,-23.53023759067],[-51.08329512267,-23.52978018202],[-51.08005769639,-23.52984412096]]],"terms_url":"http://siglon.londrina.pr.gov.br/","terms_text":"Prefeitura do Londrinas, PR"},{"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":"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":[[[-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-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":[[[-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":"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":"lu.geoportail.opendata.ortho2010","name":"Ortho 2010 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2010/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2013","name":"Ortho 2013 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2013/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2016","name":"Ortho 2016 geoportail.lu","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2016/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":"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":[[[-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]]]},{"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":"lu.geoportail.opendata.topo","name":"Topographical Map geoportail.lu","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":"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]],[[-170.9996252,57.4005339],[-169.0007481,57.3999462],[-168.9994704,56.3988562],[-171.0011935,56.3991836],[-170.9996252,57.4005339]]]},{"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"}];
18618
18619 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/drag_lift":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"drag_lift"},"name":"Drag Lift"},"aerialway/gondola":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"gondola"},"name":"Gondola"},"aerialway/goods":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"goods"},"name":"Goods Aerialway"},"aerialway/magic_carpet":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"magic_carpet"},"name":"Magic Carpet Lift"},"aerialway/mixed_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"mixed_lift"},"name":"Mixed 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":{"icon":"aerialway","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"],"fields":["ref"],"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":{"icon":"airport","geometry":["point","area"],"terms":["airport","aerodrome"],"fields":["operator","building_area"],"tags":{"aeroway":"terminal"},"name":"Airport Terminal"},"amenity/coworking_space":{"icon":"commercial","fields":["address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"tags":{"amenity":"coworking_space"},"name":"Coworking Space","searchable":false},"amenity/nursing_home":{"icon":"wheelchair","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"tags":{"amenity":"nursing_home"},"name":"Nursing Home","searchable":false},"amenity/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"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":{"icon":"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/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":"drinking-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","infirmary","institution","sanatorium","sanitarium","sick","surgery","ward"],"tags":{"amenity":"hospital"},"name":"Hospital Grounds"},"amenity/hunting_stand":{"geometry":["point","vertex","area"],"terms":["game","gun","lookout","rifle","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-alt1","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":"buddhism","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":"recycling","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":{"icon":"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","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"social_facility"},"name":"Social Facility"},"amenity/social_facility/food_bank":{"fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours"],"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","social_facility","social_facility_for","opening_hours","wheelchair"],"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","social_facility","social_facility_for","opening_hours","wheelchair","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/social_facility/nursing_home":{"icon":"wheelchair","fields":["operator","address","building_area","social_facility","social_facility_for","opening_hours","wheelchair"],"geometry":["point","area"],"terms":["elderly","living","nursing","old","senior"],"tags":{"amenity":"social_facility","social_facility":"nursing_home","social_facility:for":"senior"},"name":"Nursing Home"},"amenity/studio":{"icon":"karaoke","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":"toilet","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":"veterinary","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":"drinking-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-alt1","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/border_control":{"icon":"roadblock","fields":["access","building_area"],"geometry":["vertex","area"],"tags":{"barrier":"border_control"},"name":"Border Control"},"barrier/cattle_grid":{"icon":"barrier","geometry":["vertex"],"tags":{"barrier":"cattle_grid"},"name":"Cattle Grid"},"barrier/city_wall":{"icon":"barrier","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":"fence","fields":["fence_type","height"],"geometry":["line"],"tags":{"barrier":"fence"},"name":"Fence","matchScore":0.25},"barrier/gate":{"icon":"barrier","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":"barrier","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","building_area"],"geometry":["vertex","area"],"tags":{"barrier":"toll_booth"},"name":"Toll Booth"},"barrier/wall":{"icon":"barrier","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":"home","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-alt1","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":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"apartments"},"matchScore":0.5,"name":"Apartments"},"building/barn":{"icon":"farm","fields":["address","levels"],"geometry":["area"],"tags":{"building":"barn"},"matchScore":0.5,"name":"Barn"},"building/cabin":{"icon":"home","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":"home","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":"garden-center","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":"home","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":"industry","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":"residential-community","fields":["address","levels"],"geometry":["area"],"tags":{"building":"residential"},"matchScore":0.5,"name":"Residential Building"},"building/retail":{"icon":"commercial","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"retail"},"matchScore":0.5,"name":"Retail Building"},"building/roof":{"icon":"shelter","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":"home","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":"home","fields":["address","levels"],"geometry":["area"],"tags":{"building":"shed"},"matchScore":0.5,"name":"Shed"},"building/stable":{"icon":"horse-riding","fields":["address","levels"],"geometry":["area"],"tags":{"building":"stable"},"matchScore":0.5,"name":"Stable"},"building/static_caravan":{"icon":"home","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":"restaurant","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":"attraction","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"photographer"},"name":"Photographer"},"craft/photographic_laboratory":{"icon":"attraction","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":"logging","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":{"icon":"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","fire_hydrant/position"],"geometry":["point","vertex"],"terms":["fire plug"],"tags":{"emergency":"fire_hydrant"},"name":"Fire Hydrant"},"emergency/phone":{"icon":"emergency-phone","fields":["operator"],"geometry":["point","vertex"],"tags":{"emergency":"phone"},"name":"Emergency Phone"},"entrance":{"icon":"entrance-alt1","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":"blood-bank","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","toll","ref"],"geometry":["line"],"tags":{"highway":"motorway"},"terms":["autobahn","expressway","freeway","highway","interstate","parkway","thruway","turnpike"],"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","step_count"],"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":["tracktype","surface","width","structure","access","incline","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","toll","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":{"icon":"castle","fields":["castle_type","building_area"],"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":{"icon":"landmark","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":"*"},"matchScore":0.9,"name":"Land Use"},"landuse/farm":{"icon":"farm","fields":["operator","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/aquaculture":{"icon":"aquarium","fields":["operator","produce"],"geometry":["area"],"tags":{"landuse":"aquaculture"},"terms":["fish farm","crustacean","algae","aquafarming","shrimp farm","oyster farm","mariculture","algaculture"],"name":"Aquaculture"},"landuse/basin":{"icon":"water","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":["operator","crop","produce"],"geometry":["area"],"tags":{"landuse":"farmland"},"terms":["crop","grow","plant"],"name":"Farmland"},"landuse/farmyard":{"icon":"farm","fields":["operator","crop"],"geometry":["area"],"tags":{"landuse":"farmyard"},"terms":["crop","grow","plant"],"name":"Farmyard"},"landuse/forest":{"icon":"park-alt1","fields":["leaf_type","leaf_cycle","produce"],"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":"industry","geometry":["area"],"tags":{"landuse":"industrial"},"terms":[],"matchScore":0.9,"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":[],"matchScore":0.9,"name":"Military Area"},"landuse/military/airfield":{"icon":"airfield","fields":["ref","iata","icao"],"geometry":["point","area"],"tags":{"military":"airfield"},"addTags":{"landuse":"military","military":"airfield"},"removeTags":{"landuse":"military","military":"airfield"},"terms":["air force","army","base","bomb","fight","force","guard","heli*","jet","marine","navy","plane","troop","war"],"name":"Military Airfield"},"landuse/military/barracks":{"fields":["building_area"],"geometry":["point","area"],"tags":{"military":"barracks"},"addTags":{"landuse":"military","military":"barracks"},"removeTags":{"landuse":"military","military":"barracks"},"terms":["air force","army","base","fight","force","guard","marine","navy","troop","war"],"name":"Barracks"},"landuse/military/bunker":{"fields":["bunker_type","building_area"],"geometry":["point","area"],"tags":{"military":"bunker"},"addTags":{"building":"bunker","landuse":"military","military":"bunker"},"removeTags":{"building":"bunker","landuse":"military","military":"bunker"},"terms":["air force","army","base","fight","force","guard","marine","navy","troop","war"],"name":"Military Bunker"},"landuse/military/checkpoint":{"geometry":["point","vertex","area"],"tags":{"military":"checkpoint"},"addTags":{"landuse":"military","military":"checkpoint"},"removeTags":{"landuse":"military","military":"checkpoint"},"terms":["air force","army","base","force","guard","marine","navy","troop","war"],"name":"Checkpoint"},"landuse/military/danger_area":{"icon":"danger","geometry":["point","vertex","area"],"tags":{"military":"danger_area"},"addTags":{"landuse":"military","military":"danger_area"},"removeTags":{"landuse":"military","military":"danger_area"},"terms":["air force","army","base","blast","bomb","explo*","force","guard","mine","marine","navy","troop","war"],"name":"Danger Area"},"landuse/military/naval_base":{"geometry":["point","area"],"tags":{"military":"naval_base"},"addTags":{"landuse":"military","military":"naval_base"},"removeTags":{"landuse":"military","military":"naval_base"},"terms":["base","fight","force","guard","marine","navy","ship","sub","troop","war"],"name":"Naval Base"},"landuse/military/nuclear_explosion_site":{"icon":"danger","geometry":["point","vertex","area"],"tags":{"military":"nuclear_explosion_site"},"addTags":{"landuse":"military","military":"nuclear_explosion_site"},"removeTags":{"landuse":"military","military":"nuclear_explosion_site"},"terms":["atom","blast","bomb","detonat*","nuke","site","test"],"name":"Nuclear Explosion Site"},"landuse/military/obstacle_course":{"geometry":["point","area"],"tags":{"military":"obstacle_course"},"addTags":{"landuse":"military","military":"obstacle_course"},"removeTags":{"landuse":"military","military":"obstacle_course"},"terms":["army","base","force","guard","marine","navy","troop","war"],"name":"Obstacle Course"},"landuse/military/office":{"fields":["building_area"],"geometry":["point","area"],"tags":{"military":"office"},"addTags":{"landuse":"military","military":"office"},"removeTags":{"landuse":"military","military":"office"},"terms":["air force","army","base","enlist","fight","force","guard","marine","navy","recruit","troop","war"],"name":"Military Office"},"landuse/military/range":{"geometry":["point","area"],"tags":{"military":"range"},"addTags":{"landuse":"military","military":"range"},"removeTags":{"landuse":"military","military":"range"},"terms":["air force","army","base","fight","fire","force","guard","gun","marine","navy","rifle","shoot*","snip*","train","troop","war"],"name":"Military Range"},"landuse/military/training_area":{"geometry":["point","area"],"tags":{"military":"training_area"},"addTags":{"landuse":"military","military":"training_area"},"removeTags":{"landuse":"military","military":"training_area"},"terms":["air force","army","base","fight","fire","force","guard","gun","marine","navy","rifle","shoot*","snip*","train","troop","war"],"name":"Training Area"},"landuse/orchard":{"icon":"park-alt1","fields":["operator","trees"],"geometry":["area"],"tags":{"landuse":"orchard"},"terms":["fruit"],"name":"Orchard"},"landuse/plant_nursery":{"icon":"garden","fields":["operator","plant"],"geometry":["area"],"tags":{"landuse":"plant_nursery"},"terms":["flower","garden","grow","vivero"],"name":"Plant Nursery"},"landuse/quarry":{"geometry":["area"],"tags":{"landuse":"quarry"},"terms":[],"name":"Quarry"},"landuse/recreation_ground":{"icon":"pitch","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":{"fields":["operator"],"geometry":["area"],"tags":{"landuse":"vineyard"},"terms":["grape","wine"],"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/horse_riding":{"icon":"horse-riding","fields":["access_simple","operator","address","building"],"geometry":["point","area"],"terms":["equestrian","stable"],"tags":{"leisure":"horse_riding"},"name":"Horseback Riding Facility"},"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":{"icon":"picnic-site","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":{"icon":"embassy","geometry":["point"],"tags":{"man_made":"flagpole"},"name":"Flagpole"},"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":"attraction","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":"attraction","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":{"icon":"water","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":{"icon":"industry","fields":["operator","address","building_area","product"],"geometry":["point","area"],"terms":["assembly","build","brewery","car","plant","plastic","processing","manufacture","refinery"],"tags":{"man_made":"works"},"name":"Factory"},"natural":{"fields":["natural"],"geometry":["point","vertex","area"],"tags":{"natural":"*"},"name":"Natural"},"natural/bare_rock":{"geometry":["area"],"tags":{"natural":"bare_rock"},"terms":["rock"],"name":"Bare Rock"},"natural/bay":{"geometry":["point","area"],"tags":{"natural":"bay"},"terms":[],"name":"Bay"},"natural/beach":{"fields":["surface"],"geometry":["point","area"],"tags":{"natural":"beach"},"terms":["shore"],"name":"Beach"},"natural/cave_entrance":{"geometry":["point","area"],"fields":["fee","access_simple"],"tags":{"natural":"cave_entrance"},"terms":["cavern","hollow","grotto","shelter","cavity"],"name":"Cave Entrance"},"natural/cliff":{"icon":"triangle","geometry":["point","vertex","line","area"],"tags":{"natural":"cliff"},"terms":["escarpment"],"name":"Cliff"},"natural/coastline":{"geometry":["line"],"tags":{"natural":"coastline"},"terms":["shore"],"name":"Coastline"},"natural/fell":{"geometry":["area"],"tags":{"natural":"fell"},"terms":[],"name":"Fell"},"natural/glacier":{"geometry":["area"],"tags":{"natural":"glacier"},"terms":[],"name":"Glacier"},"natural/grassland":{"geometry":["area"],"tags":{"natural":"grassland"},"terms":["prairie","savanna"],"name":"Grassland"},"natural/heath":{"geometry":["area"],"tags":{"natural":"heath"},"terms":[],"name":"Heath"},"natural/peak":{"icon":"mountain","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/ridge":{"geometry":["line"],"tags":{"natural":"ridge"},"terms":["crest"],"name":"Ridge"},"natural/saddle":{"icon":"triangle-stroked","fields":["elevation"],"geometry":["point","vertex"],"tags":{"natural":"saddle"},"terms":["pass","mountain pass","top"],"name":"Saddle"},"natural/sand":{"geometry":["area"],"tags":{"natural":"sand"},"terms":["desert"],"name":"Sand"},"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"],"tags":{"natural":"spring"},"terms":[],"name":"Spring"},"natural/tree_row":{"icon":"park","fields":["leaf_type","leaf_cycle","denotation"],"geometry":["line"],"tags":{"natural":"tree_row"},"terms":[],"name":"Tree row"},"natural/tree":{"icon":"park","fields":["leaf_type_singular","leaf_cycle_singular","denotation"],"geometry":["point","vertex"],"tags":{"natural":"tree"},"terms":[],"name":"Tree"},"natural/volcano":{"icon":"volcano","fields":["elevation"],"geometry":["point","vertex"],"tags":{"natural":"volcano"},"terms":["mountain","crater"],"name":"Volcano"},"natural/water":{"icon":"water","fields":["water"],"geometry":["area"],"tags":{"natural":"water"},"name":"Water"},"natural/water/lake":{"icon":"water","geometry":["area"],"tags":{"natural":"water","water":"lake"},"terms":["lakelet","loch","mere"],"name":"Lake"},"natural/water/pond":{"icon":"water","geometry":["area"],"tags":{"natural":"water","water":"pond"},"terms":["lakelet","millpond","tarn","pool","mere"],"name":"Pond"},"natural/water/reservoir":{"icon":"water","geometry":["area"],"tags":{"natural":"water","water":"reservoir"},"name":"Reservoir"},"natural/wetland":{"icon":"wetland","fields":["wetland"],"geometry":["point","area"],"tags":{"natural":"wetland"},"terms":[],"name":"Wetland"},"natural/wood":{"icon":"park-alt1","fields":["leaf_type","leaf_cycle"],"geometry":["point","area"],"tags":{"natural":"wood"},"terms":["tree"],"name":"Wood"},"noexit/yes":{"icon":"barrier","geometry":["vertex"],"terms":["no exit","road end","dead end"],"tags":{"noexit":"yes"},"name":"No Exit"},"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/coworking":{"icon":"commercial","fields":["address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"terms":["coworking","office"],"tags":{"office":"coworking"},"name":"Coworking Space"},"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/lawyer/notary":{"icon":"suitcase","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"lawyer","lawyer":"notary"},"terms":["clerk","signature","wills","deeds","estate"],"name":"Notary 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/square":{"geometry":["point","area"],"tags":{"place":"square"},"name":"Square"},"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":{"icon":"power-line","geometry":["line"],"tags":{"power":"line"},"name":"Power Line"},"power/minor_line":{"icon":"power-line","geometry":["line"],"tags":{"power":"minor_line"},"name":"Minor Power Line"},"power/plant":{"icon":"industry","fields":["operator"],"geometry":["area"],"tags":{"power":"plant"},"addTags":{"power":"plant","landuse":"industrial"},"removeTags":{"power":"plant","landuse":"industrial"},"terms":["coal","gas","generat*","hydro","nuclear","power","station"],"name":"Power Station Grounds"},"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":{"icon":"bus","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":{"icon":"railway-rail","geometry":["line"],"terms":["venicular","cliff railway","cable car","cable railway","funicular railway"],"fields":["structure","gauge","service_rail"],"tags":{"railway":"funicular"},"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":{"icon":"rail","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":"entrance","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":"florist","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":"garden-center","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":"mobile-phone","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":"attraction","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":"teahouse","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":"gaming","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/watches":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"watches"},"name":"Watches Shop"},"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":"aquarium","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":{"icon":"information","fields":["information","operator","address","building_area"],"geometry":["point","vertex","area"],"tags":{"tourism":"information"},"name":"Information"},"tourism/information/board":{"icon":"information","fields":["operator","board_type"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"board"},"name":"Information Board"},"tourism/information/guidepost":{"icon":"information","fields":["operator","ref"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"guidepost"},"name":"Guidepost"},"tourism/information/map":{"icon":"information","fields":["operator","map_type","map_size"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"map"},"name":"Map"},"tourism/information/office":{"icon":"information","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":"picnic-site","fields":["operator","address","smoking"],"geometry":["point","vertex","area"],"terms":["camp"],"tags":{"tourism":"picnic_site"},"name":"Picnic Site"},"tourism/theme_park":{"icon":"amusement-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":"drinking-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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/МТС":{"tags":{"name":"МТС","shop":"mobile_phone"},"name":"МТС","icon":"mobile-phone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Евросеть":{"tags":{"name":"Евросеть","shop":"mobile_phone"},"name":"Евросеть","icon":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Связной":{"tags":{"name":"Связной","shop":"mobile_phone"},"name":"Связной","icon":"mobile-phone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Мегафон":{"tags":{"name":"Мегафон","shop":"mobile_phone"},"name":"Мегафон","icon":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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":"mobile-phone","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}};
18620
18621 var defaults = {"area":["category-landuse","category-building","category-water-area","category-natural-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","category-natural-line","power/line","line"],"point":["category-natural-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"]};
18622
18623 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":"landuse","members":["landuse/residential","landuse/industrial","landuse/commercial","landuse/retail","landuse/farmland","landuse/farmyard","landuse/forest","landuse/meadow","landuse/aquaculture","landuse/cemetery","landuse/military"]},"category-natural-area":{"geometry":"area","name":"Natural Features","icon":"natural","members":["natural/water","natural/wood","natural/scrub","natural/wetland","natural/grassland","natural/heath","natural/bare_rock","natural/beach","natural/cave_entrance","natural/glacier"]},"category-natural-line":{"geometry":"line","name":"Natural Features","icon":"natural","members":["natural/coastline","natural/tree_row"]},"category-natural-point":{"geometry":"point","name":"Natural Features","icon":"natural","members":["natural/peak","natural/cliff","natural/beach","natural/cave_entrance"]},"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/living_street","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"]}};
18624
18625 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:block_number","addr:city","addr:block_number","addr:conscriptionnumber","addr:county","addr:country","addr:county","addr:district","addr:floor","addr:hamlet","addr:housename","addr:housenumber","addr:neighbourhood","addr:place","addr:postcode","addr:province","addr:quarter","addr:state","addr:street","addr:subdistrict","addr:suburb"],"reference":{"key":"addr"},"icon":"address","universal":true,"label":"Address","strings":{"placeholders":{"block_number":"Block Number","block_number!jp":"Block No.","city":"City","city!jp":"City/Town/Village/Tokyo Special Ward","city!vn":"City/Town","conscriptionnumber":"123","country":"Country","county":"County","county!jp":"District","district":"District","district!vn":"Arrondissement/Town/District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","housenumber!jp":"Building No./Lot No.","neighbourhood":"Neighbourhood","neighbourhood!jp":"Chōme/Aza/Koaza","place":"Place","postcode":"Postcode","province":"Province","province!jp":"Prefecture","quarter":"Quarter","quarter!jp":"Ōaza/Machi","state":"State","street":"Street","subdistrict":"Subdistrict","subdistrict!vn":"Ward/Commune/Townlet","suburb":"Suburb","suburb!jp":"Ward"}}},"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"},"bunker_type":{"key":"bunker_type","type":"combo","label":"Type"},"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"}}},"castle_type":{"key":"castle_type","type":"combo","label":"Type"},"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"},"email":{"key":"email","type":"email","placeholder":"example@example.com","universal":true,"label":"Email"},"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","universal":true,"placeholder":"+31 42 123 4567"},"fee":{"key":"fee","type":"check","label":"Fee"},"fence_type":{"key":"fence_type","type":"combo","label":"Type"},"fire_hydrant/position":{"key":"fire_hydrant:position","type":"combo","label":"Position","strings":{"options":{"lane":"Lane","parking_lot":"Parking Lot","sidewalk":"Sidewalk","green":"Green"}}},"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":"check","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"},"plant":{"key":"plant","type":"combo","label":"Plant"},"population":{"key":"population","type":"text","label":"Population"},"power_supply":{"key":"power_supply","type":"check","label":"Power Supply"},"power":{"key":"power","type":"typeCombo","label":"Type"},"produce":{"key":"produce","type":"combo","label":"Produce"},"product":{"key":"product","type":"combo","label":"Product"},"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":"combo","label":"People Served"},"social_facility":{"key":"social_facility","type":"combo","label":"Type"},"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"},"step_count":{"key":"step_count","type":"number","label":"Number of Steps"},"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"}}},"toll":{"key":"toll","type":"check","label":"Toll"},"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"}};
18626
18627 var all = ["aerialway","airfield","airport","alcohol-shop","america-football","amusement-park","aquarium","art-gallery","attraction","bakery","bank","bar","barrier","baseball","basketball","bbq","beer","bicycle","bicycle-share","blood-bank","buddhism","building","building-alt1","bus","cafe","campsite","car","castle","cemetery","cinema","circle","circle-stroked","city","clothing-store","college","commercial","cricket","cross","dam","danger","defibrillator","dentist","doctor","dog-park","drinking-water","embassy","emergency-phone","entrance","entrance-alt1","farm","fast-food","fence","ferry","fire-station","florist","fuel","gaming","garden","garden-center","gift","golf","grocery","hairdresser","harbor","heart","heliport","home","horse-riding","hospital","ice-cream","industry","information","karaoke","landmark","landuse","laundry","library","lighthouse","lodging","logging","marker","marker-stroked","mobile-phone","monument","mountain","museum","music","natural","park","park-alt1","parking","parking-garage","pharmacy","picnic-site","pitch","place-of-worship","playground","police","post","prison","rail","rail-light","rail-metro","ranger-station","recycling","religious-christian","religious-jewish","religious-muslim","residential-community","restaurant","roadblock","rocket","school","scooter","shelter","shop","skiing","slaughterhouse","snowmobile","soccer","square","square-stroked","stadium","star","star-stroked","suitcase","sushi","swimming","teahouse","telephone","tennis","theatre","toilet","town","town-hall","triangle","triangle-stroked","veterinary","village","volcano","warehouse","waste-basket","water","wetland","wheelchair","zoo"];
18628 var all$1 = {
18629         all: all
18630 };
18631
18632 var all$2 = Object.freeze({
18633         all: all,
18634         default: all$1
18635 });
18636
18637 var Airport = ["airfield","airport","heliport","rocket"];
18638 var Dining = ["bakery","bar","beer","cafe","fast-food","ice-cream","restaurant"];
18639 var Education = ["college","school"];
18640 var General = ["alcohol-shop","amusement-park","aquarium","art-gallery","attraction","bank","bicycle","bicycle-share","car","castle","cinema","circle","circle-stroked","clothing-store","drinking-water","embassy","fire-station","fuel","grocery","harbor","information","laundry","library","lodging","marker","monument","museum","music","place-of-worship","police","post","prison","religious-christian","religious-jewish","religious-muslim","shop","stadium","star","suitcase","swimming","theatre","toilet","town-hall","triangle","triangle-stroked","veterinary"];
18641 var Health = ["dentist","doctor","hospital","pharmacy"];
18642 var Outdoors = ["campsite","cemetery","dog-park","garden","golf","park","picnic-site","playground","zoo"];
18643 var Transit = ["bus","ferry"];
18644 var streets = {
18645         Airport: Airport,
18646         Dining: Dining,
18647         Education: Education,
18648         General: General,
18649         Health: Health,
18650         Outdoors: Outdoors,
18651         Transit: Transit,
18652         "Mountain peak": ["mountain","volcano"],
18653         "Rail station": ["entrance","rail","rail-light","rail-metro"]
18654 };
18655
18656 var streets$1 = Object.freeze({
18657         Airport: Airport,
18658         Dining: Dining,
18659         Education: Education,
18660         General: General,
18661         Health: Health,
18662         Outdoors: Outdoors,
18663         Transit: Transit,
18664         default: streets
18665 });
18666
18667 var require$$0 = ( all$2 && all$1 ) || all$2;
18668
18669 var require$$1 = ( streets$1 && streets ) || streets$1;
18670
18671 var index$1 = {
18672   layouts: {
18673     all: require$$0,
18674     streets: require$$1
18675   }
18676 };
18677
18678 var dataFeatureIcons = index$1.layouts.all.all;
18679
18680 var data = {
18681     imagery: dataImagery,
18682     presets: {
18683         presets: presets,
18684         defaults: defaults,
18685         categories: categories,
18686         fields: fields
18687     }
18688 };
18689
18690 function osmEntity$$1(attrs) {
18691     // For prototypal inheritance.
18692     if (this instanceof osmEntity$$1) return;
18693
18694     // Create the appropriate subtype.
18695     if (attrs && attrs.type) {
18696         return osmEntity$$1[attrs.type].apply(this, arguments);
18697     } else if (attrs && attrs.id) {
18698         return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18699     }
18700
18701     // Initialize a generic Entity (used only in tests).
18702     return (new osmEntity$$1()).initialize(arguments);
18703 }
18704
18705
18706 osmEntity$$1.id = function(type) {
18707     return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18708 };
18709
18710
18711 osmEntity$$1.id.next = {
18712     node: -1, way: -1, relation: -1
18713 };
18714
18715
18716 osmEntity$$1.id.fromOSM = function(type, id) {
18717     return type[0] + id;
18718 };
18719
18720
18721 osmEntity$$1.id.toOSM = function(id) {
18722     return id.slice(1);
18723 };
18724
18725
18726 osmEntity$$1.id.type = function(id) {
18727     return { 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
18728 };
18729
18730
18731 // A function suitable for use as the second argument to d3.selection#data().
18732 osmEntity$$1.key = function(entity) {
18733     return entity.id + 'v' + (entity.v || 0);
18734 };
18735
18736
18737 osmEntity$$1.prototype = {
18738
18739     tags: {},
18740
18741
18742     initialize: function(sources) {
18743         for (var i = 0; i < sources.length; ++i) {
18744             var source = sources[i];
18745             for (var prop in source) {
18746                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
18747                     if (source[prop] === undefined) {
18748                         delete this[prop];
18749                     } else {
18750                         this[prop] = source[prop];
18751                     }
18752                 }
18753             }
18754         }
18755
18756         if (!this.id && this.type) {
18757             this.id = osmEntity$$1.id(this.type);
18758         }
18759         if (!this.hasOwnProperty('visible')) {
18760             this.visible = true;
18761         }
18762
18763         if (debug) {
18764             Object.freeze(this);
18765             Object.freeze(this.tags);
18766
18767             if (this.loc) Object.freeze(this.loc);
18768             if (this.nodes) Object.freeze(this.nodes);
18769             if (this.members) Object.freeze(this.members);
18770         }
18771
18772         return this;
18773     },
18774
18775
18776     copy: function(resolver, copies) {
18777         if (copies[this.id])
18778             return copies[this.id];
18779
18780         var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
18781         copies[this.id] = copy;
18782
18783         return copy;
18784     },
18785
18786
18787     osmId: function() {
18788         return osmEntity$$1.id.toOSM(this.id);
18789     },
18790
18791
18792     isNew: function() {
18793         return this.osmId() < 0;
18794     },
18795
18796
18797     update: function(attrs) {
18798         return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
18799     },
18800
18801
18802     mergeTags: function(tags) {
18803         var merged = lodash.clone(this.tags), changed = false;
18804         for (var k in tags) {
18805             var t1 = merged[k],
18806                 t2 = tags[k];
18807             if (!t1) {
18808                 changed = true;
18809                 merged[k] = t2;
18810             } else if (t1 !== t2) {
18811                 changed = true;
18812                 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
18813             }
18814         }
18815         return changed ? this.update({tags: merged}) : this;
18816     },
18817
18818
18819     intersects: function(extent, resolver) {
18820         return this.extent(resolver).intersects(extent);
18821     },
18822
18823
18824     isUsed: function(resolver) {
18825         return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
18826             resolver.parentRelations(this).length > 0;
18827     },
18828
18829
18830     hasInterestingTags: function() {
18831         return lodash.keys(this.tags).some(osmIsInterestingTag);
18832     },
18833
18834
18835     isHighwayIntersection: function() {
18836         return false;
18837     },
18838
18839     isDegenerate: function() {
18840         return true;
18841     },
18842
18843     deprecatedTags: function() {
18844         var tags = lodash.toPairs(this.tags);
18845         var deprecated = {};
18846
18847         dataDeprecated.forEach(function(d) {
18848             var match = lodash.toPairs(d.old)[0];
18849             tags.forEach(function(t) {
18850                 if (t[0] === match[0] &&
18851                     (t[1] === match[1] || match[1] === '*')) {
18852                     deprecated[t[0]] = t[1];
18853                 }
18854             });
18855         });
18856
18857         return deprecated;
18858     }
18859 };
18860
18861 function geoRoundCoords(c) {
18862     return [Math.floor(c[0]), Math.floor(c[1])];
18863 }
18864
18865
18866 function geoInterp(p1, p2, t) {
18867     return [p1[0] + (p2[0] - p1[0]) * t,
18868             p1[1] + (p2[1] - p1[1]) * t];
18869 }
18870
18871
18872 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
18873 // Returns a positive value, if OAB makes a counter-clockwise turn,
18874 // negative for clockwise turn, and zero if the points are collinear.
18875 function geoCross(o, a, b) {
18876     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
18877 }
18878
18879
18880 // http://jsperf.com/id-dist-optimization
18881 function geoEuclideanDistance(a, b) {
18882     var x = a[0] - b[0], y = a[1] - b[1];
18883     return Math.sqrt((x * x) + (y * y));
18884 }
18885
18886
18887 // using WGS84 polar radius (6356752.314245179 m)
18888 // const = 2 * PI * r / 360
18889 function geoLatToMeters(dLat) {
18890     return dLat * 110946.257617;
18891 }
18892
18893
18894 // using WGS84 equatorial radius (6378137.0 m)
18895 // const = 2 * PI * r / 360
18896 function geoLonToMeters(dLon, atLat) {
18897     return Math.abs(atLat) >= 90 ? 0 :
18898         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
18899 }
18900
18901
18902 // using WGS84 polar radius (6356752.314245179 m)
18903 // const = 2 * PI * r / 360
18904 function geoMetersToLat(m) {
18905     return m / 110946.257617;
18906 }
18907
18908
18909 // using WGS84 equatorial radius (6378137.0 m)
18910 // const = 2 * PI * r / 360
18911 function geoMetersToLon(m, atLat) {
18912     return Math.abs(atLat) >= 90 ? 0 :
18913         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
18914 }
18915
18916
18917 function geoOffsetToMeters(offset) {
18918     var equatRadius = 6356752.314245179,
18919         polarRadius = 6378137.0,
18920         tileSize = 256;
18921
18922     return [
18923         offset[0] * 2 * Math.PI * equatRadius / tileSize,
18924         -offset[1] * 2 * Math.PI * polarRadius / tileSize
18925     ];
18926 }
18927
18928
18929 function geoMetersToOffset(meters) {
18930     var equatRadius = 6356752.314245179,
18931         polarRadius = 6378137.0,
18932         tileSize = 256;
18933
18934     return [
18935         meters[0] * tileSize / (2 * Math.PI * equatRadius),
18936         -meters[1] * tileSize / (2 * Math.PI * polarRadius)
18937     ];
18938 }
18939
18940
18941 // Equirectangular approximation of spherical distances on Earth
18942 function geoSphericalDistance(a, b) {
18943     var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
18944         y = geoLatToMeters(a[1] - b[1]);
18945     return Math.sqrt((x * x) + (y * y));
18946 }
18947
18948
18949 function geoEdgeEqual(a, b) {
18950     return (a[0] === b[0] && a[1] === b[1]) ||
18951         (a[0] === b[1] && a[1] === b[0]);
18952 }
18953
18954
18955 // Return the counterclockwise angle in the range (-pi, pi)
18956 // between the positive X axis and the line intersecting a and b.
18957 function geoAngle(a, b, projection) {
18958     a = projection(a.loc);
18959     b = projection(b.loc);
18960     return Math.atan2(b[1] - a[1], b[0] - a[0]);
18961 }
18962
18963
18964 // Rotate all points counterclockwise around a pivot point by given angle
18965 function geoRotate(points, angle, around) {
18966     return points.map(function(point) {
18967         var radial = [point[0] - around[0], point[1] - around[1]];
18968         return [
18969             radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
18970             radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]
18971         ];
18972     });
18973 }
18974
18975
18976 // Choose the edge with the minimal distance from `point` to its orthogonal
18977 // projection onto that edge, if such a projection exists, or the distance to
18978 // the closest vertex on that edge. Returns an object with the `index` of the
18979 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
18980 function geoChooseEdge(nodes, point, projection) {
18981     var dist = geoEuclideanDistance,
18982         points = nodes.map(function(n) { return projection(n.loc); }),
18983         min = Infinity,
18984         idx, loc;
18985
18986     function dot(p, q) {
18987         return p[0] * q[0] + p[1] * q[1];
18988     }
18989
18990     for (var i = 0; i < points.length - 1; i++) {
18991         var o = points[i],
18992             s = [points[i + 1][0] - o[0],
18993                  points[i + 1][1] - o[1]],
18994             v = [point[0] - o[0],
18995                  point[1] - o[1]],
18996             proj = dot(v, s) / dot(s, s),
18997             p;
18998
18999         if (proj < 0) {
19000             p = o;
19001         } else if (proj > 1) {
19002             p = points[i + 1];
19003         } else {
19004             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
19005         }
19006
19007         var d = dist(p, point);
19008         if (d < min) {
19009             min = d;
19010             idx = i + 1;
19011             loc = projection.invert(p);
19012         }
19013     }
19014
19015     return {
19016         index: idx,
19017         distance: min,
19018         loc: loc
19019     };
19020 }
19021
19022
19023 // Return the intersection point of 2 line segments.
19024 // From https://github.com/pgkelley4/line-segments-intersect
19025 // This uses the vector cross product approach described below:
19026 //  http://stackoverflow.com/a/565282/786339
19027 function geoLineIntersection(a, b) {
19028     function subtractPoints(point1, point2) {
19029         return [point1[0] - point2[0], point1[1] - point2[1]];
19030     }
19031     function crossProduct(point1, point2) {
19032         return point1[0] * point2[1] - point1[1] * point2[0];
19033     }
19034
19035     var p = [a[0][0], a[0][1]],
19036         p2 = [a[1][0], a[1][1]],
19037         q = [b[0][0], b[0][1]],
19038         q2 = [b[1][0], b[1][1]],
19039         r = subtractPoints(p2, p),
19040         s = subtractPoints(q2, q),
19041         uNumerator = crossProduct(subtractPoints(q, p), r),
19042         denominator = crossProduct(r, s);
19043
19044     if (uNumerator && denominator) {
19045         var u = uNumerator / denominator,
19046             t = crossProduct(subtractPoints(q, p), s) / denominator;
19047
19048         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
19049             return geoInterp(p, p2, t);
19050         }
19051     }
19052
19053     return null;
19054 }
19055
19056
19057 function geoPathIntersections(path1, path2) {
19058     var intersections = [];
19059     for (var i = 0; i < path1.length - 1; i++) {
19060         for (var j = 0; j < path2.length - 1; j++) {
19061             var a = [ path1[i], path1[i+1] ],
19062                 b = [ path2[j], path2[j+1] ],
19063                 hit = geoLineIntersection(a, b);
19064             if (hit) intersections.push(hit);
19065         }
19066     }
19067     return intersections;
19068 }
19069
19070
19071 // Return whether point is contained in polygon.
19072 //
19073 // `point` should be a 2-item array of coordinates.
19074 // `polygon` should be an array of 2-item arrays of coordinates.
19075 //
19076 // From https://github.com/substack/point-in-polygon.
19077 // ray-casting algorithm based on
19078 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
19079 //
19080 function geoPointInPolygon(point, polygon) {
19081     var x = point[0],
19082         y = point[1],
19083         inside = false;
19084
19085     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
19086         var xi = polygon[i][0], yi = polygon[i][1];
19087         var xj = polygon[j][0], yj = polygon[j][1];
19088
19089         var intersect = ((yi > y) !== (yj > y)) &&
19090             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
19091         if (intersect) inside = !inside;
19092     }
19093
19094     return inside;
19095 }
19096
19097
19098 function geoPolygonContainsPolygon(outer, inner) {
19099     return lodash.every(inner, function(point) {
19100         return geoPointInPolygon(point, outer);
19101     });
19102 }
19103
19104
19105 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
19106     function testSegments(outer, inner) {
19107         for (var i = 0; i < outer.length - 1; i++) {
19108             for (var j = 0; j < inner.length - 1; j++) {
19109                 var a = [ outer[i], outer[i+1] ],
19110                     b = [ inner[j], inner[j+1] ];
19111                 if (geoLineIntersection(a, b)) return true;
19112             }
19113         }
19114         return false;
19115     }
19116
19117     function testPoints(outer, inner) {
19118         return lodash.some(inner, function(point) {
19119             return geoPointInPolygon(point, outer);
19120         });
19121     }
19122
19123    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
19124 }
19125
19126
19127 function geoPathLength(path) {
19128     var length = 0;
19129     for (var i = 0; i < path.length - 1; i++) {
19130         length += geoEuclideanDistance(path[i], path[i + 1]);
19131     }
19132     return length;
19133 }
19134
19135 function geoExtent$$1(min, max) {
19136     if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19137     if (min instanceof geoExtent$$1) {
19138         return min;
19139     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19140         this[0] = min[0];
19141         this[1] = min[1];
19142     } else {
19143         this[0] = min        || [ Infinity,  Infinity];
19144         this[1] = max || min || [-Infinity, -Infinity];
19145     }
19146 }
19147
19148 geoExtent$$1.prototype = new Array(2);
19149
19150 lodash.extend(geoExtent$$1.prototype, {
19151
19152     equals: function (obj) {
19153         return this[0][0] === obj[0][0] &&
19154             this[0][1] === obj[0][1] &&
19155             this[1][0] === obj[1][0] &&
19156             this[1][1] === obj[1][1];
19157     },
19158
19159
19160     extend: function(obj) {
19161         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19162         return geoExtent$$1(
19163             [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19164             [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19165         );
19166     },
19167
19168
19169     _extend: function(extent) {
19170         this[0][0] = Math.min(extent[0][0], this[0][0]);
19171         this[0][1] = Math.min(extent[0][1], this[0][1]);
19172         this[1][0] = Math.max(extent[1][0], this[1][0]);
19173         this[1][1] = Math.max(extent[1][1], this[1][1]);
19174     },
19175
19176
19177     area: function() {
19178         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19179     },
19180
19181
19182     center: function() {
19183         return [(this[0][0] + this[1][0]) / 2,
19184                 (this[0][1] + this[1][1]) / 2];
19185     },
19186
19187
19188     rectangle: function() {
19189         return [this[0][0], this[0][1], this[1][0], this[1][1]];
19190     },
19191
19192
19193     bbox: function() {
19194         return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19195     },
19196
19197
19198     polygon: function() {
19199         return [
19200             [this[0][0], this[0][1]],
19201             [this[0][0], this[1][1]],
19202             [this[1][0], this[1][1]],
19203             [this[1][0], this[0][1]],
19204             [this[0][0], this[0][1]]
19205         ];
19206     },
19207
19208
19209     contains: function(obj) {
19210         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19211         return obj[0][0] >= this[0][0] &&
19212                obj[0][1] >= this[0][1] &&
19213                obj[1][0] <= this[1][0] &&
19214                obj[1][1] <= this[1][1];
19215     },
19216
19217
19218     intersects: function(obj) {
19219         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19220         return obj[0][0] <= this[1][0] &&
19221                obj[0][1] <= this[1][1] &&
19222                obj[1][0] >= this[0][0] &&
19223                obj[1][1] >= this[0][1];
19224     },
19225
19226
19227     intersection: function(obj) {
19228         if (!this.intersects(obj)) return new geoExtent$$1();
19229         return new geoExtent$$1(
19230             [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19231             [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19232         );
19233     },
19234
19235
19236     percentContainedIn: function(obj) {
19237         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19238         var a1 = this.intersection(obj).area(),
19239             a2 = this.area();
19240
19241         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19242             return 0;
19243         } else {
19244             return a1 / a2;
19245         }
19246     },
19247
19248
19249     padByMeters: function(meters) {
19250         var dLat = geoMetersToLat(meters),
19251             dLon = geoMetersToLon(meters, this.center()[1]);
19252         return geoExtent$$1(
19253             [this[0][0] - dLon, this[0][1] - dLat],
19254             [this[1][0] + dLon, this[1][1] + dLat]
19255         );
19256     },
19257
19258
19259     toParam: function() {
19260         return this.rectangle().join(',');
19261     }
19262
19263 });
19264
19265 var version = "4.5.0";
19266
19267 var ascending = function(a, b) {
19268   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19269 };
19270
19271 var bisector = function(compare) {
19272   if (compare.length === 1) compare = ascendingComparator(compare);
19273   return {
19274     left: function(a, x, lo, hi) {
19275       if (lo == null) lo = 0;
19276       if (hi == null) hi = a.length;
19277       while (lo < hi) {
19278         var mid = lo + hi >>> 1;
19279         if (compare(a[mid], x) < 0) lo = mid + 1;
19280         else hi = mid;
19281       }
19282       return lo;
19283     },
19284     right: function(a, x, lo, hi) {
19285       if (lo == null) lo = 0;
19286       if (hi == null) hi = a.length;
19287       while (lo < hi) {
19288         var mid = lo + hi >>> 1;
19289         if (compare(a[mid], x) > 0) hi = mid;
19290         else lo = mid + 1;
19291       }
19292       return lo;
19293     }
19294   };
19295 };
19296
19297 function ascendingComparator(f) {
19298   return function(d, x) {
19299     return ascending(f(d), x);
19300   };
19301 }
19302
19303 var ascendingBisect = bisector(ascending);
19304 var bisectRight = ascendingBisect.right;
19305 var bisectLeft = ascendingBisect.left;
19306
19307 var descending = function(a, b) {
19308   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19309 };
19310
19311 var number = function(x) {
19312   return x === null ? NaN : +x;
19313 };
19314
19315 var variance = function(array, f) {
19316   var n = array.length,
19317       m = 0,
19318       a,
19319       d,
19320       s = 0,
19321       i = -1,
19322       j = 0;
19323
19324   if (f == null) {
19325     while (++i < n) {
19326       if (!isNaN(a = number(array[i]))) {
19327         d = a - m;
19328         m += d / ++j;
19329         s += d * (a - m);
19330       }
19331     }
19332   }
19333
19334   else {
19335     while (++i < n) {
19336       if (!isNaN(a = number(f(array[i], i, array)))) {
19337         d = a - m;
19338         m += d / ++j;
19339         s += d * (a - m);
19340       }
19341     }
19342   }
19343
19344   if (j > 1) return s / (j - 1);
19345 };
19346
19347 var deviation = function(array, f) {
19348   var v = variance(array, f);
19349   return v ? Math.sqrt(v) : v;
19350 };
19351
19352 var extent = function(array, f) {
19353   var i = -1,
19354       n = array.length,
19355       a,
19356       b,
19357       c;
19358
19359   if (f == null) {
19360     while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
19361     while (++i < n) if ((b = array[i]) != null) {
19362       if (a > b) a = b;
19363       if (c < b) c = b;
19364     }
19365   }
19366
19367   else {
19368     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }
19369     while (++i < n) if ((b = f(array[i], i, array)) != null) {
19370       if (a > b) a = b;
19371       if (c < b) c = b;
19372     }
19373   }
19374
19375   return [a, c];
19376 };
19377
19378 var array = Array.prototype;
19379
19380 var slice = array.slice;
19381 var map = array.map;
19382
19383 var constant = function(x) {
19384   return function() {
19385     return x;
19386   };
19387 };
19388
19389 var identity = function(x) {
19390   return x;
19391 };
19392
19393 var sequence = function(start, stop, step) {
19394   start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19395
19396   var i = -1,
19397       n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19398       range = new Array(n);
19399
19400   while (++i < n) {
19401     range[i] = start + i * step;
19402   }
19403
19404   return range;
19405 };
19406
19407 var e10 = Math.sqrt(50);
19408 var e5 = Math.sqrt(10);
19409 var e2 = Math.sqrt(2);
19410
19411 var ticks = function(start, stop, count) {
19412   var step = tickStep(start, stop, count);
19413   return sequence(
19414     Math.ceil(start / step) * step,
19415     Math.floor(stop / step) * step + step / 2, // inclusive
19416     step
19417   );
19418 };
19419
19420 function tickStep(start, stop, count) {
19421   var step0 = Math.abs(stop - start) / Math.max(0, count),
19422       step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19423       error = step0 / step1;
19424   if (error >= e10) step1 *= 10;
19425   else if (error >= e5) step1 *= 5;
19426   else if (error >= e2) step1 *= 2;
19427   return stop < start ? -step1 : step1;
19428 }
19429
19430 var sturges = function(values) {
19431   return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19432 };
19433
19434 var histogram = function() {
19435   var value = identity,
19436       domain = extent,
19437       threshold = sturges;
19438
19439   function histogram(data) {
19440     var i,
19441         n = data.length,
19442         x,
19443         values = new Array(n);
19444
19445     for (i = 0; i < n; ++i) {
19446       values[i] = value(data[i], i, data);
19447     }
19448
19449     var xz = domain(values),
19450         x0 = xz[0],
19451         x1 = xz[1],
19452         tz = threshold(values, x0, x1);
19453
19454     // Convert number of thresholds into uniform thresholds.
19455     if (!Array.isArray(tz)) tz = ticks(x0, x1, tz);
19456
19457     // Remove any thresholds outside the domain.
19458     var m = tz.length;
19459     while (tz[0] <= x0) tz.shift(), --m;
19460     while (tz[m - 1] >= x1) tz.pop(), --m;
19461
19462     var bins = new Array(m + 1),
19463         bin;
19464
19465     // Initialize bins.
19466     for (i = 0; i <= m; ++i) {
19467       bin = bins[i] = [];
19468       bin.x0 = i > 0 ? tz[i - 1] : x0;
19469       bin.x1 = i < m ? tz[i] : x1;
19470     }
19471
19472     // Assign data to bins by value, ignoring any outside the domain.
19473     for (i = 0; i < n; ++i) {
19474       x = values[i];
19475       if (x0 <= x && x <= x1) {
19476         bins[bisectRight(tz, x, 0, m)].push(data[i]);
19477       }
19478     }
19479
19480     return bins;
19481   }
19482
19483   histogram.value = function(_) {
19484     return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
19485   };
19486
19487   histogram.domain = function(_) {
19488     return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
19489   };
19490
19491   histogram.thresholds = function(_) {
19492     return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold;
19493   };
19494
19495   return histogram;
19496 };
19497
19498 var threshold = function(array, p, f) {
19499   if (f == null) f = number;
19500   if (!(n = array.length)) return;
19501   if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);
19502   if (p >= 1) return +f(array[n - 1], n - 1, array);
19503   var n,
19504       h = (n - 1) * p,
19505       i = Math.floor(h),
19506       a = +f(array[i], i, array),
19507       b = +f(array[i + 1], i + 1, array);
19508   return a + (b - a) * (h - i);
19509 };
19510
19511 var freedmanDiaconis = function(values, min, max) {
19512   values = map.call(values, number).sort(ascending);
19513   return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19514 };
19515
19516 var scott = function(values, min, max) {
19517   return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19518 };
19519
19520 var max = function(array, f) {
19521   var i = -1,
19522       n = array.length,
19523       a,
19524       b;
19525
19526   if (f == null) {
19527     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19528     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
19529   }
19530
19531   else {
19532     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19533     while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;
19534   }
19535
19536   return a;
19537 };
19538
19539 var mean = function(array, f) {
19540   var s = 0,
19541       n = array.length,
19542       a,
19543       i = -1,
19544       j = n;
19545
19546   if (f == null) {
19547     while (++i < n) if (!isNaN(a = number(array[i]))) s += a; else --j;
19548   }
19549
19550   else {
19551     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) s += a; else --j;
19552   }
19553
19554   if (j) return s / j;
19555 };
19556
19557 var median = function(array, f) {
19558   var numbers = [],
19559       n = array.length,
19560       a,
19561       i = -1;
19562
19563   if (f == null) {
19564     while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a);
19565   }
19566
19567   else {
19568     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a);
19569   }
19570
19571   return threshold(numbers.sort(ascending), 0.5);
19572 };
19573
19574 var merge = function(arrays) {
19575   var n = arrays.length,
19576       m,
19577       i = -1,
19578       j = 0,
19579       merged,
19580       array;
19581
19582   while (++i < n) j += arrays[i].length;
19583   merged = new Array(j);
19584
19585   while (--n >= 0) {
19586     array = arrays[n];
19587     m = array.length;
19588     while (--m >= 0) {
19589       merged[--j] = array[m];
19590     }
19591   }
19592
19593   return merged;
19594 };
19595
19596 var min = function(array, f) {
19597   var i = -1,
19598       n = array.length,
19599       a,
19600       b;
19601
19602   if (f == null) {
19603     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19604     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
19605   }
19606
19607   else {
19608     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19609     while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;
19610   }
19611
19612   return a;
19613 };
19614
19615 var pairs = function(array) {
19616   var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19617   while (i < n) pairs[i] = [p, p = array[++i]];
19618   return pairs;
19619 };
19620
19621 var permute = function(array, indexes) {
19622   var i = indexes.length, permutes = new Array(i);
19623   while (i--) permutes[i] = array[indexes[i]];
19624   return permutes;
19625 };
19626
19627 var scan = function(array, compare) {
19628   if (!(n = array.length)) return;
19629   var i = 0,
19630       n,
19631       j = 0,
19632       xi,
19633       xj = array[j];
19634
19635   if (!compare) compare = ascending;
19636
19637   while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;
19638
19639   if (compare(xj, xj) === 0) return j;
19640 };
19641
19642 var shuffle = function(array, i0, i1) {
19643   var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19644       t,
19645       i;
19646
19647   while (m) {
19648     i = Math.random() * m-- | 0;
19649     t = array[m + i0];
19650     array[m + i0] = array[i + i0];
19651     array[i + i0] = t;
19652   }
19653
19654   return array;
19655 };
19656
19657 var sum = function(array, f) {
19658   var s = 0,
19659       n = array.length,
19660       a,
19661       i = -1;
19662
19663   if (f == null) {
19664     while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.
19665   }
19666
19667   else {
19668     while (++i < n) if (a = +f(array[i], i, array)) s += a;
19669   }
19670
19671   return s;
19672 };
19673
19674 var transpose = function(matrix) {
19675   if (!(n = matrix.length)) return [];
19676   for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19677     for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19678       row[j] = matrix[j][i];
19679     }
19680   }
19681   return transpose;
19682 };
19683
19684 function length(d) {
19685   return d.length;
19686 }
19687
19688 var zip = function() {
19689   return transpose(arguments);
19690 };
19691
19692 var slice$1 = Array.prototype.slice;
19693
19694 var identity$1 = function(x) {
19695   return x;
19696 };
19697
19698 var top = 1;
19699 var right = 2;
19700 var bottom = 3;
19701 var left = 4;
19702 var epsilon = 1e-6;
19703
19704 function translateX(scale0, scale1, d) {
19705   var x = scale0(d);
19706   return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)";
19707 }
19708
19709 function translateY(scale0, scale1, d) {
19710   var y = scale0(d);
19711   return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")";
19712 }
19713
19714 function center(scale) {
19715   var offset = scale.bandwidth() / 2;
19716   if (scale.round()) offset = Math.round(offset);
19717   return function(d) {
19718     return scale(d) + offset;
19719   };
19720 }
19721
19722 function entering() {
19723   return !this.__axis;
19724 }
19725
19726 function axis(orient, scale) {
19727   var tickArguments = [],
19728       tickValues = null,
19729       tickFormat = null,
19730       tickSizeInner = 6,
19731       tickSizeOuter = 6,
19732       tickPadding = 3;
19733
19734   function axis(context) {
19735     var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
19736         format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat,
19737         spacing = Math.max(tickSizeInner, 0) + tickPadding,
19738         transform = orient === top || orient === bottom ? translateX : translateY,
19739         range = scale.range(),
19740         range0 = range[0] + 0.5,
19741         range1 = range[range.length - 1] + 0.5,
19742         position = (scale.bandwidth ? center : identity$1)(scale.copy()),
19743         selection = context.selection ? context.selection() : context,
19744         path = selection.selectAll(".domain").data([null]),
19745         tick = selection.selectAll(".tick").data(values, scale).order(),
19746         tickExit = tick.exit(),
19747         tickEnter = tick.enter().append("g").attr("class", "tick"),
19748         line = tick.select("line"),
19749         text = tick.select("text"),
19750         k = orient === top || orient === left ? -1 : 1,
19751         x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x");
19752
19753     path = path.merge(path.enter().insert("path", ".tick")
19754         .attr("class", "domain")
19755         .attr("stroke", "#000"));
19756
19757     tick = tick.merge(tickEnter);
19758
19759     line = line.merge(tickEnter.append("line")
19760         .attr("stroke", "#000")
19761         .attr(x + "2", k * tickSizeInner)
19762         .attr(y + "1", 0.5)
19763         .attr(y + "2", 0.5));
19764
19765     text = text.merge(tickEnter.append("text")
19766         .attr("fill", "#000")
19767         .attr(x, k * spacing)
19768         .attr(y, 0.5)
19769         .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
19770
19771     if (context !== selection) {
19772       path = path.transition(context);
19773       tick = tick.transition(context);
19774       line = line.transition(context);
19775       text = text.transition(context);
19776
19777       tickExit = tickExit.transition(context)
19778           .attr("opacity", epsilon)
19779           .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); });
19780
19781       tickEnter
19782           .attr("opacity", epsilon)
19783           .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); });
19784     }
19785
19786     tickExit.remove();
19787
19788     path
19789         .attr("d", orient === left || orient == right
19790             ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
19791             : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
19792
19793     tick
19794         .attr("opacity", 1)
19795         .attr("transform", function(d) { return transform(position, position, d); });
19796
19797     line
19798         .attr(x + "2", k * tickSizeInner);
19799
19800     text
19801         .attr(x, k * spacing)
19802         .text(format);
19803
19804     selection.filter(entering)
19805         .attr("fill", "none")
19806         .attr("font-size", 10)
19807         .attr("font-family", "sans-serif")
19808         .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
19809
19810     selection
19811         .each(function() { this.__axis = position; });
19812   }
19813
19814   axis.scale = function(_) {
19815     return arguments.length ? (scale = _, axis) : scale;
19816   };
19817
19818   axis.ticks = function() {
19819     return tickArguments = slice$1.call(arguments), axis;
19820   };
19821
19822   axis.tickArguments = function(_) {
19823     return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice();
19824   };
19825
19826   axis.tickValues = function(_) {
19827     return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice();
19828   };
19829
19830   axis.tickFormat = function(_) {
19831     return arguments.length ? (tickFormat = _, axis) : tickFormat;
19832   };
19833
19834   axis.tickSize = function(_) {
19835     return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
19836   };
19837
19838   axis.tickSizeInner = function(_) {
19839     return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
19840   };
19841
19842   axis.tickSizeOuter = function(_) {
19843     return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
19844   };
19845
19846   axis.tickPadding = function(_) {
19847     return arguments.length ? (tickPadding = +_, axis) : tickPadding;
19848   };
19849
19850   return axis;
19851 }
19852
19853 function axisTop(scale) {
19854   return axis(top, scale);
19855 }
19856
19857 function axisRight(scale) {
19858   return axis(right, scale);
19859 }
19860
19861 function axisBottom(scale) {
19862   return axis(bottom, scale);
19863 }
19864
19865 function axisLeft(scale) {
19866   return axis(left, scale);
19867 }
19868
19869 var noop = {value: function() {}};
19870
19871 function dispatch() {
19872   for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
19873     if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
19874     _[t] = [];
19875   }
19876   return new Dispatch(_);
19877 }
19878
19879 function Dispatch(_) {
19880   this._ = _;
19881 }
19882
19883 function parseTypenames(typenames, types) {
19884   return typenames.trim().split(/^|\s+/).map(function(t) {
19885     var name = "", i = t.indexOf(".");
19886     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
19887     if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
19888     return {type: t, name: name};
19889   });
19890 }
19891
19892 Dispatch.prototype = dispatch.prototype = {
19893   constructor: Dispatch,
19894   on: function(typename, callback) {
19895     var _ = this._,
19896         T = parseTypenames(typename + "", _),
19897         t,
19898         i = -1,
19899         n = T.length;
19900
19901     // If no callback was specified, return the callback of the given type and name.
19902     if (arguments.length < 2) {
19903       while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
19904       return;
19905     }
19906
19907     // If a type was specified, set the callback for the given type and name.
19908     // Otherwise, if a null callback was specified, remove callbacks of the given name.
19909     if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
19910     while (++i < n) {
19911       if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
19912       else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
19913     }
19914
19915     return this;
19916   },
19917   copy: function() {
19918     var copy = {}, _ = this._;
19919     for (var t in _) copy[t] = _[t].slice();
19920     return new Dispatch(copy);
19921   },
19922   call: function(type, that) {
19923     if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
19924     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
19925     for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
19926   },
19927   apply: function(type, that, args) {
19928     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
19929     for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
19930   }
19931 };
19932
19933 function get(type, name) {
19934   for (var i = 0, n = type.length, c; i < n; ++i) {
19935     if ((c = type[i]).name === name) {
19936       return c.value;
19937     }
19938   }
19939 }
19940
19941 function set(type, name, callback) {
19942   for (var i = 0, n = type.length; i < n; ++i) {
19943     if (type[i].name === name) {
19944       type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
19945       break;
19946     }
19947   }
19948   if (callback != null) type.push({name: name, value: callback});
19949   return type;
19950 }
19951
19952 var xhtml = "http://www.w3.org/1999/xhtml";
19953
19954 var namespaces = {
19955   svg: "http://www.w3.org/2000/svg",
19956   xhtml: xhtml,
19957   xlink: "http://www.w3.org/1999/xlink",
19958   xml: "http://www.w3.org/XML/1998/namespace",
19959   xmlns: "http://www.w3.org/2000/xmlns/"
19960 };
19961
19962 var namespace = function(name) {
19963   var prefix = name += "", i = prefix.indexOf(":");
19964   if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
19965   return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
19966 };
19967
19968 function creatorInherit(name) {
19969   return function() {
19970     var document = this.ownerDocument,
19971         uri = this.namespaceURI;
19972     return uri === xhtml && document.documentElement.namespaceURI === xhtml
19973         ? document.createElement(name)
19974         : document.createElementNS(uri, name);
19975   };
19976 }
19977
19978 function creatorFixed(fullname) {
19979   return function() {
19980     return this.ownerDocument.createElementNS(fullname.space, fullname.local);
19981   };
19982 }
19983
19984 var creator = function(name) {
19985   var fullname = namespace(name);
19986   return (fullname.local
19987       ? creatorFixed
19988       : creatorInherit)(fullname);
19989 };
19990
19991 var nextId = 0;
19992
19993 function local$1() {
19994   return new Local;
19995 }
19996
19997 function Local() {
19998   this._ = "@" + (++nextId).toString(36);
19999 }
20000
20001 Local.prototype = local$1.prototype = {
20002   constructor: Local,
20003   get: function(node) {
20004     var id = this._;
20005     while (!(id in node)) if (!(node = node.parentNode)) return;
20006     return node[id];
20007   },
20008   set: function(node, value) {
20009     return node[this._] = value;
20010   },
20011   remove: function(node) {
20012     return this._ in node && delete node[this._];
20013   },
20014   toString: function() {
20015     return this._;
20016   }
20017 };
20018
20019 var matcher = function(selector) {
20020   return function() {
20021     return this.matches(selector);
20022   };
20023 };
20024
20025 if (typeof document !== "undefined") {
20026   var element = document.documentElement;
20027   if (!element.matches) {
20028     var vendorMatches = element.webkitMatchesSelector
20029         || element.msMatchesSelector
20030         || element.mozMatchesSelector
20031         || element.oMatchesSelector;
20032     matcher = function(selector) {
20033       return function() {
20034         return vendorMatches.call(this, selector);
20035       };
20036     };
20037   }
20038 }
20039
20040 var matcher$1 = matcher;
20041
20042 var filterEvents = {};
20043
20044 var event = null;
20045
20046 if (typeof document !== "undefined") {
20047   var element$1 = document.documentElement;
20048   if (!("onmouseenter" in element$1)) {
20049     filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
20050   }
20051 }
20052
20053 function filterContextListener(listener, index, group) {
20054   listener = contextListener(listener, index, group);
20055   return function(event) {
20056     var related = event.relatedTarget;
20057     if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
20058       listener.call(this, event);
20059     }
20060   };
20061 }
20062
20063 function contextListener(listener, index, group) {
20064   return function(event1) {
20065     var event0 = event; // Events can be reentrant (e.g., focus).
20066     event = event1;
20067     try {
20068       listener.call(this, this.__data__, index, group);
20069     } finally {
20070       event = event0;
20071     }
20072   };
20073 }
20074
20075 function parseTypenames$1(typenames) {
20076   return typenames.trim().split(/^|\s+/).map(function(t) {
20077     var name = "", i = t.indexOf(".");
20078     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
20079     return {type: t, name: name};
20080   });
20081 }
20082
20083 function onRemove(typename) {
20084   return function() {
20085     var on = this.__on;
20086     if (!on) return;
20087     for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
20088       if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
20089         this.removeEventListener(o.type, o.listener, o.capture);
20090       } else {
20091         on[++i] = o;
20092       }
20093     }
20094     if (++i) on.length = i;
20095     else delete this.__on;
20096   };
20097 }
20098
20099 function onAdd(typename, value, capture) {
20100   var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
20101   return function(d, i, group) {
20102     var on = this.__on, o, listener = wrap(value, i, group);
20103     if (on) for (var j = 0, m = on.length; j < m; ++j) {
20104       if ((o = on[j]).type === typename.type && o.name === typename.name) {
20105         this.removeEventListener(o.type, o.listener, o.capture);
20106         this.addEventListener(o.type, o.listener = listener, o.capture = capture);
20107         o.value = value;
20108         return;
20109       }
20110     }
20111     this.addEventListener(typename.type, listener, capture);
20112     o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
20113     if (!on) this.__on = [o];
20114     else on.push(o);
20115   };
20116 }
20117
20118 var selection_on = function(typename, value, capture) {
20119   var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
20120
20121   if (arguments.length < 2) {
20122     var on = this.node().__on;
20123     if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
20124       for (i = 0, o = on[j]; i < n; ++i) {
20125         if ((t = typenames[i]).type === o.type && t.name === o.name) {
20126           return o.value;
20127         }
20128       }
20129     }
20130     return;
20131   }
20132
20133   on = value ? onAdd : onRemove;
20134   if (capture == null) capture = false;
20135   for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
20136   return this;
20137 };
20138
20139 function customEvent(event1, listener, that, args) {
20140   var event0 = event;
20141   event1.sourceEvent = event;
20142   event = event1;
20143   try {
20144     return listener.apply(that, args);
20145   } finally {
20146     event = event0;
20147   }
20148 }
20149
20150 var sourceEvent = function() {
20151   var current = event, source;
20152   while (source = current.sourceEvent) current = source;
20153   return current;
20154 };
20155
20156 var point = function(node, event) {
20157   var svg = node.ownerSVGElement || node;
20158
20159   if (svg.createSVGPoint) {
20160     var point = svg.createSVGPoint();
20161     point.x = event.clientX, point.y = event.clientY;
20162     point = point.matrixTransform(node.getScreenCTM().inverse());
20163     return [point.x, point.y];
20164   }
20165
20166   var rect = node.getBoundingClientRect();
20167   return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
20168 };
20169
20170 var mouse = function(node) {
20171   var event = sourceEvent();
20172   if (event.changedTouches) event = event.changedTouches[0];
20173   return point(node, event);
20174 };
20175
20176 function none() {}
20177
20178 var selector = function(selector) {
20179   return selector == null ? none : function() {
20180     return this.querySelector(selector);
20181   };
20182 };
20183
20184 var selection_select = function(select) {
20185   if (typeof select !== "function") select = selector(select);
20186
20187   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20188     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
20189       if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
20190         if ("__data__" in node) subnode.__data__ = node.__data__;
20191         subgroup[i] = subnode;
20192       }
20193     }
20194   }
20195
20196   return new Selection(subgroups, this._parents);
20197 };
20198
20199 function empty$1() {
20200   return [];
20201 }
20202
20203 var selectorAll = function(selector) {
20204   return selector == null ? empty$1 : function() {
20205     return this.querySelectorAll(selector);
20206   };
20207 };
20208
20209 var selection_selectAll = function(select) {
20210   if (typeof select !== "function") select = selectorAll(select);
20211
20212   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
20213     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
20214       if (node = group[i]) {
20215         subgroups.push(select.call(node, node.__data__, i, group));
20216         parents.push(node);
20217       }
20218     }
20219   }
20220
20221   return new Selection(subgroups, parents);
20222 };
20223
20224 var selection_filter = function(match) {
20225   if (typeof match !== "function") match = matcher$1(match);
20226
20227   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
20228     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
20229       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
20230         subgroup.push(node);
20231       }
20232     }
20233   }
20234
20235   return new Selection(subgroups, this._parents);
20236 };
20237
20238 var sparse = function(update) {
20239   return new Array(update.length);
20240 };
20241
20242 var selection_enter = function() {
20243   return new Selection(this._enter || this._groups.map(sparse), this._parents);
20244 };
20245
20246 function EnterNode(parent, datum) {
20247   this.ownerDocument = parent.ownerDocument;
20248   this.namespaceURI = parent.namespaceURI;
20249   this._next = null;
20250   this._parent = parent;
20251   this.__data__ = datum;
20252 }
20253
20254 EnterNode.prototype = {
20255   constructor: EnterNode,
20256   appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
20257   insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
20258   querySelector: function(selector) { return this._parent.querySelector(selector); },
20259   querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
20260 };
20261
20262 var constant$1 = function(x) {
20263   return function() {
20264     return x;
20265   };
20266 };
20267
20268 var keyPrefix = "$"; // Protect against keys like “__proto__”.
20269
20270 function bindIndex(parent, group, enter, update, exit, data) {
20271   var i = 0,
20272       node,
20273       groupLength = group.length,
20274       dataLength = data.length;
20275
20276   // Put any non-null nodes that fit into update.
20277   // Put any null nodes into enter.
20278   // Put any remaining data into enter.
20279   for (; i < dataLength; ++i) {
20280     if (node = group[i]) {
20281       node.__data__ = data[i];
20282       update[i] = node;
20283     } else {
20284       enter[i] = new EnterNode(parent, data[i]);
20285     }
20286   }
20287
20288   // Put any non-null nodes that don’t fit into exit.
20289   for (; i < groupLength; ++i) {
20290     if (node = group[i]) {
20291       exit[i] = node;
20292     }
20293   }
20294 }
20295
20296 function bindKey(parent, group, enter, update, exit, data, key) {
20297   var i,
20298       node,
20299       nodeByKeyValue = {},
20300       groupLength = group.length,
20301       dataLength = data.length,
20302       keyValues = new Array(groupLength),
20303       keyValue;
20304
20305   // Compute the key for each node.
20306   // If multiple nodes have the same key, the duplicates are added to exit.
20307   for (i = 0; i < groupLength; ++i) {
20308     if (node = group[i]) {
20309       keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
20310       if (keyValue in nodeByKeyValue) {
20311         exit[i] = node;
20312       } else {
20313         nodeByKeyValue[keyValue] = node;
20314       }
20315     }
20316   }
20317
20318   // Compute the key for each datum.
20319   // If there a node associated with this key, join and add it to update.
20320   // If there is not (or the key is a duplicate), add it to enter.
20321   for (i = 0; i < dataLength; ++i) {
20322     keyValue = keyPrefix + key.call(parent, data[i], i, data);
20323     if (node = nodeByKeyValue[keyValue]) {
20324       update[i] = node;
20325       node.__data__ = data[i];
20326       nodeByKeyValue[keyValue] = null;
20327     } else {
20328       enter[i] = new EnterNode(parent, data[i]);
20329     }
20330   }
20331
20332   // Add any remaining nodes that were not bound to data to exit.
20333   for (i = 0; i < groupLength; ++i) {
20334     if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
20335       exit[i] = node;
20336     }
20337   }
20338 }
20339
20340 var selection_data = function(value, key) {
20341   if (!value) {
20342     data = new Array(this.size()), j = -1;
20343     this.each(function(d) { data[++j] = d; });
20344     return data;
20345   }
20346
20347   var bind = key ? bindKey : bindIndex,
20348       parents = this._parents,
20349       groups = this._groups;
20350
20351   if (typeof value !== "function") value = constant$1(value);
20352
20353   for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
20354     var parent = parents[j],
20355         group = groups[j],
20356         groupLength = group.length,
20357         data = value.call(parent, parent && parent.__data__, j, parents),
20358         dataLength = data.length,
20359         enterGroup = enter[j] = new Array(dataLength),
20360         updateGroup = update[j] = new Array(dataLength),
20361         exitGroup = exit[j] = new Array(groupLength);
20362
20363     bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
20364
20365     // Now connect the enter nodes to their following update node, such that
20366     // appendChild can insert the materialized enter node before this node,
20367     // rather than at the end of the parent node.
20368     for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
20369       if (previous = enterGroup[i0]) {
20370         if (i0 >= i1) i1 = i0 + 1;
20371         while (!(next = updateGroup[i1]) && ++i1 < dataLength);
20372         previous._next = next || null;
20373       }
20374     }
20375   }
20376
20377   update = new Selection(update, parents);
20378   update._enter = enter;
20379   update._exit = exit;
20380   return update;
20381 };
20382
20383 var selection_exit = function() {
20384   return new Selection(this._exit || this._groups.map(sparse), this._parents);
20385 };
20386
20387 var selection_merge = function(selection) {
20388
20389   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) {
20390     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
20391       if (node = group0[i] || group1[i]) {
20392         merge[i] = node;
20393       }
20394     }
20395   }
20396
20397   for (; j < m0; ++j) {
20398     merges[j] = groups0[j];
20399   }
20400
20401   return new Selection(merges, this._parents);
20402 };
20403
20404 var selection_order = function() {
20405
20406   for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
20407     for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
20408       if (node = group[i]) {
20409         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
20410         next = node;
20411       }
20412     }
20413   }
20414
20415   return this;
20416 };
20417
20418 var selection_sort = function(compare) {
20419   if (!compare) compare = ascending$1;
20420
20421   function compareNode(a, b) {
20422     return a && b ? compare(a.__data__, b.__data__) : !a - !b;
20423   }
20424
20425   for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
20426     for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
20427       if (node = group[i]) {
20428         sortgroup[i] = node;
20429       }
20430     }
20431     sortgroup.sort(compareNode);
20432   }
20433
20434   return new Selection(sortgroups, this._parents).order();
20435 };
20436
20437 function ascending$1(a, b) {
20438   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
20439 }
20440
20441 var selection_call = function() {
20442   var callback = arguments[0];
20443   arguments[0] = this;
20444   callback.apply(null, arguments);
20445   return this;
20446 };
20447
20448 var selection_nodes = function() {
20449   var nodes = new Array(this.size()), i = -1;
20450   this.each(function() { nodes[++i] = this; });
20451   return nodes;
20452 };
20453
20454 var selection_node = function() {
20455
20456   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20457     for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
20458       var node = group[i];
20459       if (node) return node;
20460     }
20461   }
20462
20463   return null;
20464 };
20465
20466 var selection_size = function() {
20467   var size = 0;
20468   this.each(function() { ++size; });
20469   return size;
20470 };
20471
20472 var selection_empty = function() {
20473   return !this.node();
20474 };
20475
20476 var selection_each = function(callback) {
20477
20478   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
20479     for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
20480       if (node = group[i]) callback.call(node, node.__data__, i, group);
20481     }
20482   }
20483
20484   return this;
20485 };
20486
20487 function attrRemove(name) {
20488   return function() {
20489     this.removeAttribute(name);
20490   };
20491 }
20492
20493 function attrRemoveNS(fullname) {
20494   return function() {
20495     this.removeAttributeNS(fullname.space, fullname.local);
20496   };
20497 }
20498
20499 function attrConstant(name, value) {
20500   return function() {
20501     this.setAttribute(name, value);
20502   };
20503 }
20504
20505 function attrConstantNS(fullname, value) {
20506   return function() {
20507     this.setAttributeNS(fullname.space, fullname.local, value);
20508   };
20509 }
20510
20511 function attrFunction(name, value) {
20512   return function() {
20513     var v = value.apply(this, arguments);
20514     if (v == null) this.removeAttribute(name);
20515     else this.setAttribute(name, v);
20516   };
20517 }
20518
20519 function attrFunctionNS(fullname, value) {
20520   return function() {
20521     var v = value.apply(this, arguments);
20522     if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
20523     else this.setAttributeNS(fullname.space, fullname.local, v);
20524   };
20525 }
20526
20527 var selection_attr = function(name, value) {
20528   var fullname = namespace(name);
20529
20530   if (arguments.length < 2) {
20531     var node = this.node();
20532     return fullname.local
20533         ? node.getAttributeNS(fullname.space, fullname.local)
20534         : node.getAttribute(fullname);
20535   }
20536
20537   return this.each((value == null
20538       ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
20539       ? (fullname.local ? attrFunctionNS : attrFunction)
20540       : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
20541 };
20542
20543 var window$1 = function(node) {
20544   return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
20545       || (node.document && node) // node is a Window
20546       || node.defaultView; // node is a Document
20547 };
20548
20549 function styleRemove(name) {
20550   return function() {
20551     this.style.removeProperty(name);
20552   };
20553 }
20554
20555 function styleConstant(name, value, priority) {
20556   return function() {
20557     this.style.setProperty(name, value, priority);
20558   };
20559 }
20560
20561 function styleFunction(name, value, priority) {
20562   return function() {
20563     var v = value.apply(this, arguments);
20564     if (v == null) this.style.removeProperty(name);
20565     else this.style.setProperty(name, v, priority);
20566   };
20567 }
20568
20569 var selection_style = function(name, value, priority) {
20570   var node;
20571   return arguments.length > 1
20572       ? this.each((value == null
20573             ? styleRemove : typeof value === "function"
20574             ? styleFunction
20575             : styleConstant)(name, value, priority == null ? "" : priority))
20576       : window$1(node = this.node())
20577           .getComputedStyle(node, null)
20578           .getPropertyValue(name);
20579 };
20580
20581 function propertyRemove(name) {
20582   return function() {
20583     delete this[name];
20584   };
20585 }
20586
20587 function propertyConstant(name, value) {
20588   return function() {
20589     this[name] = value;
20590   };
20591 }
20592
20593 function propertyFunction(name, value) {
20594   return function() {
20595     var v = value.apply(this, arguments);
20596     if (v == null) delete this[name];
20597     else this[name] = v;
20598   };
20599 }
20600
20601 var selection_property = function(name, value) {
20602   return arguments.length > 1
20603       ? this.each((value == null
20604           ? propertyRemove : typeof value === "function"
20605           ? propertyFunction
20606           : propertyConstant)(name, value))
20607       : this.node()[name];
20608 };
20609
20610 function classArray(string) {
20611   return string.trim().split(/^|\s+/);
20612 }
20613
20614 function classList(node) {
20615   return node.classList || new ClassList(node);
20616 }
20617
20618 function ClassList(node) {
20619   this._node = node;
20620   this._names = classArray(node.getAttribute("class") || "");
20621 }
20622
20623 ClassList.prototype = {
20624   add: function(name) {
20625     var i = this._names.indexOf(name);
20626     if (i < 0) {
20627       this._names.push(name);
20628       this._node.setAttribute("class", this._names.join(" "));
20629     }
20630   },
20631   remove: function(name) {
20632     var i = this._names.indexOf(name);
20633     if (i >= 0) {
20634       this._names.splice(i, 1);
20635       this._node.setAttribute("class", this._names.join(" "));
20636     }
20637   },
20638   contains: function(name) {
20639     return this._names.indexOf(name) >= 0;
20640   }
20641 };
20642
20643 function classedAdd(node, names) {
20644   var list = classList(node), i = -1, n = names.length;
20645   while (++i < n) list.add(names[i]);
20646 }
20647
20648 function classedRemove(node, names) {
20649   var list = classList(node), i = -1, n = names.length;
20650   while (++i < n) list.remove(names[i]);
20651 }
20652
20653 function classedTrue(names) {
20654   return function() {
20655     classedAdd(this, names);
20656   };
20657 }
20658
20659 function classedFalse(names) {
20660   return function() {
20661     classedRemove(this, names);
20662   };
20663 }
20664
20665 function classedFunction(names, value) {
20666   return function() {
20667     (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
20668   };
20669 }
20670
20671 var selection_classed = function(name, value) {
20672   var names = classArray(name + "");
20673
20674   if (arguments.length < 2) {
20675     var list = classList(this.node()), i = -1, n = names.length;
20676     while (++i < n) if (!list.contains(names[i])) return false;
20677     return true;
20678   }
20679
20680   return this.each((typeof value === "function"
20681       ? classedFunction : value
20682       ? classedTrue
20683       : classedFalse)(names, value));
20684 };
20685
20686 function textRemove() {
20687   this.textContent = "";
20688 }
20689
20690 function textConstant(value) {
20691   return function() {
20692     this.textContent = value;
20693   };
20694 }
20695
20696 function textFunction(value) {
20697   return function() {
20698     var v = value.apply(this, arguments);
20699     this.textContent = v == null ? "" : v;
20700   };
20701 }
20702
20703 var selection_text = function(value) {
20704   return arguments.length
20705       ? this.each(value == null
20706           ? textRemove : (typeof value === "function"
20707           ? textFunction
20708           : textConstant)(value))
20709       : this.node().textContent;
20710 };
20711
20712 function htmlRemove() {
20713   this.innerHTML = "";
20714 }
20715
20716 function htmlConstant(value) {
20717   return function() {
20718     this.innerHTML = value;
20719   };
20720 }
20721
20722 function htmlFunction(value) {
20723   return function() {
20724     var v = value.apply(this, arguments);
20725     this.innerHTML = v == null ? "" : v;
20726   };
20727 }
20728
20729 var selection_html = function(value) {
20730   return arguments.length
20731       ? this.each(value == null
20732           ? htmlRemove : (typeof value === "function"
20733           ? htmlFunction
20734           : htmlConstant)(value))
20735       : this.node().innerHTML;
20736 };
20737
20738 function raise() {
20739   if (this.nextSibling) this.parentNode.appendChild(this);
20740 }
20741
20742 var selection_raise = function() {
20743   return this.each(raise);
20744 };
20745
20746 function lower() {
20747   if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
20748 }
20749
20750 var selection_lower = function() {
20751   return this.each(lower);
20752 };
20753
20754 var selection_append = function(name) {
20755   var create = typeof name === "function" ? name : creator(name);
20756   return this.select(function() {
20757     return this.appendChild(create.apply(this, arguments));
20758   });
20759 };
20760
20761 function constantNull() {
20762   return null;
20763 }
20764
20765 var selection_insert = function(name, before) {
20766   var create = typeof name === "function" ? name : creator(name),
20767       select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
20768   return this.select(function() {
20769     return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
20770   });
20771 };
20772
20773 function remove() {
20774   var parent = this.parentNode;
20775   if (parent) parent.removeChild(this);
20776 }
20777
20778 var selection_remove = function() {
20779   return this.each(remove);
20780 };
20781
20782 var selection_datum = function(value) {
20783   return arguments.length
20784       ? this.property("__data__", value)
20785       : this.node().__data__;
20786 };
20787
20788 function dispatchEvent(node, type, params) {
20789   var window = window$1(node),
20790       event = window.CustomEvent;
20791
20792   if (event) {
20793     event = new event(type, params);
20794   } else {
20795     event = window.document.createEvent("Event");
20796     if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
20797     else event.initEvent(type, false, false);
20798   }
20799
20800   node.dispatchEvent(event);
20801 }
20802
20803 function dispatchConstant(type, params) {
20804   return function() {
20805     return dispatchEvent(this, type, params);
20806   };
20807 }
20808
20809 function dispatchFunction(type, params) {
20810   return function() {
20811     return dispatchEvent(this, type, params.apply(this, arguments));
20812   };
20813 }
20814
20815 var selection_dispatch = function(type, params) {
20816   return this.each((typeof params === "function"
20817       ? dispatchFunction
20818       : dispatchConstant)(type, params));
20819 };
20820
20821 var root = [null];
20822
20823 function Selection(groups, parents) {
20824   this._groups = groups;
20825   this._parents = parents;
20826 }
20827
20828 function selection() {
20829   return new Selection([[document.documentElement]], root);
20830 }
20831
20832 Selection.prototype = selection.prototype = {
20833   constructor: Selection,
20834   select: selection_select,
20835   selectAll: selection_selectAll,
20836   filter: selection_filter,
20837   data: selection_data,
20838   enter: selection_enter,
20839   exit: selection_exit,
20840   merge: selection_merge,
20841   order: selection_order,
20842   sort: selection_sort,
20843   call: selection_call,
20844   nodes: selection_nodes,
20845   node: selection_node,
20846   size: selection_size,
20847   empty: selection_empty,
20848   each: selection_each,
20849   attr: selection_attr,
20850   style: selection_style,
20851   property: selection_property,
20852   classed: selection_classed,
20853   text: selection_text,
20854   html: selection_html,
20855   raise: selection_raise,
20856   lower: selection_lower,
20857   append: selection_append,
20858   insert: selection_insert,
20859   remove: selection_remove,
20860   datum: selection_datum,
20861   on: selection_on,
20862   dispatch: selection_dispatch
20863 };
20864
20865 var select = function(selector) {
20866   return typeof selector === "string"
20867       ? new Selection([[document.querySelector(selector)]], [document.documentElement])
20868       : new Selection([[selector]], root);
20869 };
20870
20871 var selectAll = function(selector) {
20872   return typeof selector === "string"
20873       ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
20874       : new Selection([selector == null ? [] : selector], root);
20875 };
20876
20877 var touch = function(node, touches, identifier) {
20878   if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
20879
20880   for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
20881     if ((touch = touches[i]).identifier === identifier) {
20882       return point(node, touch);
20883     }
20884   }
20885
20886   return null;
20887 };
20888
20889 var touches = function(node, touches) {
20890   if (touches == null) touches = sourceEvent().touches;
20891
20892   for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
20893     points[i] = point(node, touches[i]);
20894   }
20895
20896   return points;
20897 };
20898
20899 function nopropagation() {
20900   event.stopImmediatePropagation();
20901 }
20902
20903 var noevent = function() {
20904   event.preventDefault();
20905   event.stopImmediatePropagation();
20906 };
20907
20908 var dragDisable = function(view) {
20909   var root = view.document.documentElement,
20910       selection$$1 = select(view).on("dragstart.drag", noevent, true);
20911   if ("onselectstart" in root) {
20912     selection$$1.on("selectstart.drag", noevent, true);
20913   } else {
20914     root.__noselect = root.style.MozUserSelect;
20915     root.style.MozUserSelect = "none";
20916   }
20917 };
20918
20919 function yesdrag(view, noclick) {
20920   var root = view.document.documentElement,
20921       selection$$1 = select(view).on("dragstart.drag", null);
20922   if (noclick) {
20923     selection$$1.on("click.drag", noevent, true);
20924     setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
20925   }
20926   if ("onselectstart" in root) {
20927     selection$$1.on("selectstart.drag", null);
20928   } else {
20929     root.style.MozUserSelect = root.__noselect;
20930     delete root.__noselect;
20931   }
20932 }
20933
20934 var constant$2 = function(x) {
20935   return function() {
20936     return x;
20937   };
20938 };
20939
20940 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
20941   this.target = target;
20942   this.type = type;
20943   this.subject = subject;
20944   this.identifier = id;
20945   this.active = active;
20946   this.x = x;
20947   this.y = y;
20948   this.dx = dx;
20949   this.dy = dy;
20950   this._ = dispatch;
20951 }
20952
20953 DragEvent.prototype.on = function() {
20954   var value = this._.on.apply(this._, arguments);
20955   return value === this._ ? this : value;
20956 };
20957
20958 // Ignore right-click, since that should open the context menu.
20959 function defaultFilter$1() {
20960   return !event.button;
20961 }
20962
20963 function defaultContainer() {
20964   return this.parentNode;
20965 }
20966
20967 function defaultSubject(d) {
20968   return d == null ? {x: event.x, y: event.y} : d;
20969 }
20970
20971 var drag = function() {
20972   var filter = defaultFilter$1,
20973       container = defaultContainer,
20974       subject = defaultSubject,
20975       gestures = {},
20976       listeners = dispatch("start", "drag", "end"),
20977       active = 0,
20978       mousemoving,
20979       touchending;
20980
20981   function drag(selection$$1) {
20982     selection$$1
20983         .on("mousedown.drag", mousedowned)
20984         .on("touchstart.drag", touchstarted)
20985         .on("touchmove.drag", touchmoved)
20986         .on("touchend.drag touchcancel.drag", touchended)
20987         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
20988   }
20989
20990   function mousedowned() {
20991     if (touchending || !filter.apply(this, arguments)) return;
20992     var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
20993     if (!gesture) return;
20994     select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
20995     dragDisable(event.view);
20996     nopropagation();
20997     mousemoving = false;
20998     gesture("start");
20999   }
21000
21001   function mousemoved() {
21002     noevent();
21003     mousemoving = true;
21004     gestures.mouse("drag");
21005   }
21006
21007   function mouseupped() {
21008     select(event.view).on("mousemove.drag mouseup.drag", null);
21009     yesdrag(event.view, mousemoving);
21010     noevent();
21011     gestures.mouse("end");
21012   }
21013
21014   function touchstarted() {
21015     if (!filter.apply(this, arguments)) return;
21016     var touches$$1 = event.changedTouches,
21017         c = container.apply(this, arguments),
21018         n = touches$$1.length, i, gesture;
21019
21020     for (i = 0; i < n; ++i) {
21021       if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
21022         nopropagation();
21023         gesture("start");
21024       }
21025     }
21026   }
21027
21028   function touchmoved() {
21029     var touches$$1 = event.changedTouches,
21030         n = touches$$1.length, i, gesture;
21031
21032     for (i = 0; i < n; ++i) {
21033       if (gesture = gestures[touches$$1[i].identifier]) {
21034         noevent();
21035         gesture("drag");
21036       }
21037     }
21038   }
21039
21040   function touchended() {
21041     var touches$$1 = event.changedTouches,
21042         n = touches$$1.length, i, gesture;
21043
21044     if (touchending) clearTimeout(touchending);
21045     touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
21046     for (i = 0; i < n; ++i) {
21047       if (gesture = gestures[touches$$1[i].identifier]) {
21048         nopropagation();
21049         gesture("end");
21050       }
21051     }
21052   }
21053
21054   function beforestart(id, container, point, that, args) {
21055     var p = point(container, id), s, dx, dy,
21056         sublisteners = listeners.copy();
21057
21058     if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
21059       if ((event.subject = s = subject.apply(that, args)) == null) return false;
21060       dx = s.x - p[0] || 0;
21061       dy = s.y - p[1] || 0;
21062       return true;
21063     })) return;
21064
21065     return function gesture(type) {
21066       var p0 = p, n;
21067       switch (type) {
21068         case "start": gestures[id] = gesture, n = active++; break;
21069         case "end": delete gestures[id], --active; // nobreak
21070         case "drag": p = point(container, id), n = active; break;
21071       }
21072       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]);
21073     };
21074   }
21075
21076   drag.filter = function(_) {
21077     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
21078   };
21079
21080   drag.container = function(_) {
21081     return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
21082   };
21083
21084   drag.subject = function(_) {
21085     return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
21086   };
21087
21088   drag.on = function() {
21089     var value = listeners.on.apply(listeners, arguments);
21090     return value === listeners ? drag : value;
21091   };
21092
21093   return drag;
21094 };
21095
21096 var define = function(constructor, factory, prototype) {
21097   constructor.prototype = factory.prototype = prototype;
21098   prototype.constructor = constructor;
21099 };
21100
21101 function extend(parent, definition) {
21102   var prototype = Object.create(parent.prototype);
21103   for (var key in definition) prototype[key] = definition[key];
21104   return prototype;
21105 }
21106
21107 function Color() {}
21108
21109 var darker = 0.7;
21110 var brighter = 1 / darker;
21111
21112 var reI = "\\s*([+-]?\\d+)\\s*";
21113 var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
21114 var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
21115 var reHex3 = /^#([0-9a-f]{3})$/;
21116 var reHex6 = /^#([0-9a-f]{6})$/;
21117 var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
21118 var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
21119 var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
21120 var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
21121 var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
21122 var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
21123
21124 var named = {
21125   aliceblue: 0xf0f8ff,
21126   antiquewhite: 0xfaebd7,
21127   aqua: 0x00ffff,
21128   aquamarine: 0x7fffd4,
21129   azure: 0xf0ffff,
21130   beige: 0xf5f5dc,
21131   bisque: 0xffe4c4,
21132   black: 0x000000,
21133   blanchedalmond: 0xffebcd,
21134   blue: 0x0000ff,
21135   blueviolet: 0x8a2be2,
21136   brown: 0xa52a2a,
21137   burlywood: 0xdeb887,
21138   cadetblue: 0x5f9ea0,
21139   chartreuse: 0x7fff00,
21140   chocolate: 0xd2691e,
21141   coral: 0xff7f50,
21142   cornflowerblue: 0x6495ed,
21143   cornsilk: 0xfff8dc,
21144   crimson: 0xdc143c,
21145   cyan: 0x00ffff,
21146   darkblue: 0x00008b,
21147   darkcyan: 0x008b8b,
21148   darkgoldenrod: 0xb8860b,
21149   darkgray: 0xa9a9a9,
21150   darkgreen: 0x006400,
21151   darkgrey: 0xa9a9a9,
21152   darkkhaki: 0xbdb76b,
21153   darkmagenta: 0x8b008b,
21154   darkolivegreen: 0x556b2f,
21155   darkorange: 0xff8c00,
21156   darkorchid: 0x9932cc,
21157   darkred: 0x8b0000,
21158   darksalmon: 0xe9967a,
21159   darkseagreen: 0x8fbc8f,
21160   darkslateblue: 0x483d8b,
21161   darkslategray: 0x2f4f4f,
21162   darkslategrey: 0x2f4f4f,
21163   darkturquoise: 0x00ced1,
21164   darkviolet: 0x9400d3,
21165   deeppink: 0xff1493,
21166   deepskyblue: 0x00bfff,
21167   dimgray: 0x696969,
21168   dimgrey: 0x696969,
21169   dodgerblue: 0x1e90ff,
21170   firebrick: 0xb22222,
21171   floralwhite: 0xfffaf0,
21172   forestgreen: 0x228b22,
21173   fuchsia: 0xff00ff,
21174   gainsboro: 0xdcdcdc,
21175   ghostwhite: 0xf8f8ff,
21176   gold: 0xffd700,
21177   goldenrod: 0xdaa520,
21178   gray: 0x808080,
21179   green: 0x008000,
21180   greenyellow: 0xadff2f,
21181   grey: 0x808080,
21182   honeydew: 0xf0fff0,
21183   hotpink: 0xff69b4,
21184   indianred: 0xcd5c5c,
21185   indigo: 0x4b0082,
21186   ivory: 0xfffff0,
21187   khaki: 0xf0e68c,
21188   lavender: 0xe6e6fa,
21189   lavenderblush: 0xfff0f5,
21190   lawngreen: 0x7cfc00,
21191   lemonchiffon: 0xfffacd,
21192   lightblue: 0xadd8e6,
21193   lightcoral: 0xf08080,
21194   lightcyan: 0xe0ffff,
21195   lightgoldenrodyellow: 0xfafad2,
21196   lightgray: 0xd3d3d3,
21197   lightgreen: 0x90ee90,
21198   lightgrey: 0xd3d3d3,
21199   lightpink: 0xffb6c1,
21200   lightsalmon: 0xffa07a,
21201   lightseagreen: 0x20b2aa,
21202   lightskyblue: 0x87cefa,
21203   lightslategray: 0x778899,
21204   lightslategrey: 0x778899,
21205   lightsteelblue: 0xb0c4de,
21206   lightyellow: 0xffffe0,
21207   lime: 0x00ff00,
21208   limegreen: 0x32cd32,
21209   linen: 0xfaf0e6,
21210   magenta: 0xff00ff,
21211   maroon: 0x800000,
21212   mediumaquamarine: 0x66cdaa,
21213   mediumblue: 0x0000cd,
21214   mediumorchid: 0xba55d3,
21215   mediumpurple: 0x9370db,
21216   mediumseagreen: 0x3cb371,
21217   mediumslateblue: 0x7b68ee,
21218   mediumspringgreen: 0x00fa9a,
21219   mediumturquoise: 0x48d1cc,
21220   mediumvioletred: 0xc71585,
21221   midnightblue: 0x191970,
21222   mintcream: 0xf5fffa,
21223   mistyrose: 0xffe4e1,
21224   moccasin: 0xffe4b5,
21225   navajowhite: 0xffdead,
21226   navy: 0x000080,
21227   oldlace: 0xfdf5e6,
21228   olive: 0x808000,
21229   olivedrab: 0x6b8e23,
21230   orange: 0xffa500,
21231   orangered: 0xff4500,
21232   orchid: 0xda70d6,
21233   palegoldenrod: 0xeee8aa,
21234   palegreen: 0x98fb98,
21235   paleturquoise: 0xafeeee,
21236   palevioletred: 0xdb7093,
21237   papayawhip: 0xffefd5,
21238   peachpuff: 0xffdab9,
21239   peru: 0xcd853f,
21240   pink: 0xffc0cb,
21241   plum: 0xdda0dd,
21242   powderblue: 0xb0e0e6,
21243   purple: 0x800080,
21244   rebeccapurple: 0x663399,
21245   red: 0xff0000,
21246   rosybrown: 0xbc8f8f,
21247   royalblue: 0x4169e1,
21248   saddlebrown: 0x8b4513,
21249   salmon: 0xfa8072,
21250   sandybrown: 0xf4a460,
21251   seagreen: 0x2e8b57,
21252   seashell: 0xfff5ee,
21253   sienna: 0xa0522d,
21254   silver: 0xc0c0c0,
21255   skyblue: 0x87ceeb,
21256   slateblue: 0x6a5acd,
21257   slategray: 0x708090,
21258   slategrey: 0x708090,
21259   snow: 0xfffafa,
21260   springgreen: 0x00ff7f,
21261   steelblue: 0x4682b4,
21262   tan: 0xd2b48c,
21263   teal: 0x008080,
21264   thistle: 0xd8bfd8,
21265   tomato: 0xff6347,
21266   turquoise: 0x40e0d0,
21267   violet: 0xee82ee,
21268   wheat: 0xf5deb3,
21269   white: 0xffffff,
21270   whitesmoke: 0xf5f5f5,
21271   yellow: 0xffff00,
21272   yellowgreen: 0x9acd32
21273 };
21274
21275 define(Color, color, {
21276   displayable: function() {
21277     return this.rgb().displayable();
21278   },
21279   toString: function() {
21280     return this.rgb() + "";
21281   }
21282 });
21283
21284 function color(format) {
21285   var m;
21286   format = (format + "").trim().toLowerCase();
21287   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
21288       : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
21289       : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
21290       : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
21291       : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
21292       : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
21293       : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
21294       : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
21295       : named.hasOwnProperty(format) ? rgbn(named[format])
21296       : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
21297       : null;
21298 }
21299
21300 function rgbn(n) {
21301   return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
21302 }
21303
21304 function rgba(r, g, b, a) {
21305   if (a <= 0) r = g = b = NaN;
21306   return new Rgb(r, g, b, a);
21307 }
21308
21309 function rgbConvert(o) {
21310   if (!(o instanceof Color)) o = color(o);
21311   if (!o) return new Rgb;
21312   o = o.rgb();
21313   return new Rgb(o.r, o.g, o.b, o.opacity);
21314 }
21315
21316 function rgb(r, g, b, opacity) {
21317   return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
21318 }
21319
21320 function Rgb(r, g, b, opacity) {
21321   this.r = +r;
21322   this.g = +g;
21323   this.b = +b;
21324   this.opacity = +opacity;
21325 }
21326
21327 define(Rgb, rgb, extend(Color, {
21328   brighter: function(k) {
21329     k = k == null ? brighter : Math.pow(brighter, k);
21330     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21331   },
21332   darker: function(k) {
21333     k = k == null ? darker : Math.pow(darker, k);
21334     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
21335   },
21336   rgb: function() {
21337     return this;
21338   },
21339   displayable: function() {
21340     return (0 <= this.r && this.r <= 255)
21341         && (0 <= this.g && this.g <= 255)
21342         && (0 <= this.b && this.b <= 255)
21343         && (0 <= this.opacity && this.opacity <= 1);
21344   },
21345   toString: function() {
21346     var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
21347     return (a === 1 ? "rgb(" : "rgba(")
21348         + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
21349         + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
21350         + Math.max(0, Math.min(255, Math.round(this.b) || 0))
21351         + (a === 1 ? ")" : ", " + a + ")");
21352   }
21353 }));
21354
21355 function hsla(h, s, l, a) {
21356   if (a <= 0) h = s = l = NaN;
21357   else if (l <= 0 || l >= 1) h = s = NaN;
21358   else if (s <= 0) h = NaN;
21359   return new Hsl(h, s, l, a);
21360 }
21361
21362 function hslConvert(o) {
21363   if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
21364   if (!(o instanceof Color)) o = color(o);
21365   if (!o) return new Hsl;
21366   if (o instanceof Hsl) return o;
21367   o = o.rgb();
21368   var r = o.r / 255,
21369       g = o.g / 255,
21370       b = o.b / 255,
21371       min = Math.min(r, g, b),
21372       max = Math.max(r, g, b),
21373       h = NaN,
21374       s = max - min,
21375       l = (max + min) / 2;
21376   if (s) {
21377     if (r === max) h = (g - b) / s + (g < b) * 6;
21378     else if (g === max) h = (b - r) / s + 2;
21379     else h = (r - g) / s + 4;
21380     s /= l < 0.5 ? max + min : 2 - max - min;
21381     h *= 60;
21382   } else {
21383     s = l > 0 && l < 1 ? 0 : h;
21384   }
21385   return new Hsl(h, s, l, o.opacity);
21386 }
21387
21388 function hsl(h, s, l, opacity) {
21389   return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
21390 }
21391
21392 function Hsl(h, s, l, opacity) {
21393   this.h = +h;
21394   this.s = +s;
21395   this.l = +l;
21396   this.opacity = +opacity;
21397 }
21398
21399 define(Hsl, hsl, extend(Color, {
21400   brighter: function(k) {
21401     k = k == null ? brighter : Math.pow(brighter, k);
21402     return new Hsl(this.h, this.s, this.l * k, this.opacity);
21403   },
21404   darker: function(k) {
21405     k = k == null ? darker : Math.pow(darker, k);
21406     return new Hsl(this.h, this.s, this.l * k, this.opacity);
21407   },
21408   rgb: function() {
21409     var h = this.h % 360 + (this.h < 0) * 360,
21410         s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
21411         l = this.l,
21412         m2 = l + (l < 0.5 ? l : 1 - l) * s,
21413         m1 = 2 * l - m2;
21414     return new Rgb(
21415       hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
21416       hsl2rgb(h, m1, m2),
21417       hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
21418       this.opacity
21419     );
21420   },
21421   displayable: function() {
21422     return (0 <= this.s && this.s <= 1 || isNaN(this.s))
21423         && (0 <= this.l && this.l <= 1)
21424         && (0 <= this.opacity && this.opacity <= 1);
21425   }
21426 }));
21427
21428 /* From FvD 13.37, CSS Color Module Level 3 */
21429 function hsl2rgb(h, m1, m2) {
21430   return (h < 60 ? m1 + (m2 - m1) * h / 60
21431       : h < 180 ? m2
21432       : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
21433       : m1) * 255;
21434 }
21435
21436 var deg2rad = Math.PI / 180;
21437 var rad2deg = 180 / Math.PI;
21438
21439 var Kn = 18;
21440 var Xn = 0.950470;
21441 var Yn = 1;
21442 var Zn = 1.088830;
21443 var t0 = 4 / 29;
21444 var t1 = 6 / 29;
21445 var t2 = 3 * t1 * t1;
21446 var t3 = t1 * t1 * t1;
21447
21448 function labConvert(o) {
21449   if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
21450   if (o instanceof Hcl) {
21451     var h = o.h * deg2rad;
21452     return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
21453   }
21454   if (!(o instanceof Rgb)) o = rgbConvert(o);
21455   var b = rgb2xyz(o.r),
21456       a = rgb2xyz(o.g),
21457       l = rgb2xyz(o.b),
21458       x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
21459       y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
21460       z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
21461   return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
21462 }
21463
21464 function lab(l, a, b, opacity) {
21465   return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
21466 }
21467
21468 function Lab(l, a, b, opacity) {
21469   this.l = +l;
21470   this.a = +a;
21471   this.b = +b;
21472   this.opacity = +opacity;
21473 }
21474
21475 define(Lab, lab, extend(Color, {
21476   brighter: function(k) {
21477     return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21478   },
21479   darker: function(k) {
21480     return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
21481   },
21482   rgb: function() {
21483     var y = (this.l + 16) / 116,
21484         x = isNaN(this.a) ? y : y + this.a / 500,
21485         z = isNaN(this.b) ? y : y - this.b / 200;
21486     y = Yn * lab2xyz(y);
21487     x = Xn * lab2xyz(x);
21488     z = Zn * lab2xyz(z);
21489     return new Rgb(
21490       xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
21491       xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
21492       xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
21493       this.opacity
21494     );
21495   }
21496 }));
21497
21498 function xyz2lab(t) {
21499   return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
21500 }
21501
21502 function lab2xyz(t) {
21503   return t > t1 ? t * t * t : t2 * (t - t0);
21504 }
21505
21506 function xyz2rgb(x) {
21507   return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
21508 }
21509
21510 function rgb2xyz(x) {
21511   return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
21512 }
21513
21514 function hclConvert(o) {
21515   if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
21516   if (!(o instanceof Lab)) o = labConvert(o);
21517   var h = Math.atan2(o.b, o.a) * rad2deg;
21518   return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
21519 }
21520
21521 function hcl(h, c, l, opacity) {
21522   return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
21523 }
21524
21525 function Hcl(h, c, l, opacity) {
21526   this.h = +h;
21527   this.c = +c;
21528   this.l = +l;
21529   this.opacity = +opacity;
21530 }
21531
21532 define(Hcl, hcl, extend(Color, {
21533   brighter: function(k) {
21534     return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
21535   },
21536   darker: function(k) {
21537     return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
21538   },
21539   rgb: function() {
21540     return labConvert(this).rgb();
21541   }
21542 }));
21543
21544 var A = -0.14861;
21545 var B = +1.78277;
21546 var C = -0.29227;
21547 var D = -0.90649;
21548 var E = +1.97294;
21549 var ED = E * D;
21550 var EB = E * B;
21551 var BC_DA = B * C - D * A;
21552
21553 function cubehelixConvert(o) {
21554   if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
21555   if (!(o instanceof Rgb)) o = rgbConvert(o);
21556   var r = o.r / 255,
21557       g = o.g / 255,
21558       b = o.b / 255,
21559       l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
21560       bl = b - l,
21561       k = (E * (g - l) - C * bl) / D,
21562       s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
21563       h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
21564   return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
21565 }
21566
21567 function cubehelix(h, s, l, opacity) {
21568   return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
21569 }
21570
21571 function Cubehelix(h, s, l, opacity) {
21572   this.h = +h;
21573   this.s = +s;
21574   this.l = +l;
21575   this.opacity = +opacity;
21576 }
21577
21578 define(Cubehelix, cubehelix, extend(Color, {
21579   brighter: function(k) {
21580     k = k == null ? brighter : Math.pow(brighter, k);
21581     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21582   },
21583   darker: function(k) {
21584     k = k == null ? darker : Math.pow(darker, k);
21585     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
21586   },
21587   rgb: function() {
21588     var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
21589         l = +this.l,
21590         a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
21591         cosh = Math.cos(h),
21592         sinh = Math.sin(h);
21593     return new Rgb(
21594       255 * (l + a * (A * cosh + B * sinh)),
21595       255 * (l + a * (C * cosh + D * sinh)),
21596       255 * (l + a * (E * cosh)),
21597       this.opacity
21598     );
21599   }
21600 }));
21601
21602 function basis(t1, v0, v1, v2, v3) {
21603   var t2 = t1 * t1, t3 = t2 * t1;
21604   return ((1 - 3 * t1 + 3 * t2 - t3) * v0
21605       + (4 - 6 * t2 + 3 * t3) * v1
21606       + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
21607       + t3 * v3) / 6;
21608 }
21609
21610 var constant$3 = function(x) {
21611   return function() {
21612     return x;
21613   };
21614 };
21615
21616 function linear(a, d) {
21617   return function(t) {
21618     return a + t * d;
21619   };
21620 }
21621
21622 function exponential(a, b, y) {
21623   return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
21624     return Math.pow(a + t * b, y);
21625   };
21626 }
21627
21628 function hue(a, b) {
21629   var d = b - a;
21630   return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
21631 }
21632
21633 function gamma(y) {
21634   return (y = +y) === 1 ? nogamma : function(a, b) {
21635     return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a);
21636   };
21637 }
21638
21639 function nogamma(a, b) {
21640   var d = b - a;
21641   return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
21642 }
21643
21644 var interpolateRgb = ((function rgbGamma(y) {
21645   var color$$1 = gamma(y);
21646
21647   function rgb$$1(start, end) {
21648     var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
21649         g = color$$1(start.g, end.g),
21650         b = color$$1(start.b, end.b),
21651         opacity = color$$1(start.opacity, end.opacity);
21652     return function(t) {
21653       start.r = r(t);
21654       start.g = g(t);
21655       start.b = b(t);
21656       start.opacity = opacity(t);
21657       return start + "";
21658     };
21659   }
21660
21661   rgb$$1.gamma = rgbGamma;
21662
21663   return rgb$$1;
21664 }))(1);
21665
21666 var array$1 = function(a, b) {
21667   var nb = b ? b.length : 0,
21668       na = a ? Math.min(nb, a.length) : 0,
21669       x = new Array(nb),
21670       c = new Array(nb),
21671       i;
21672
21673   for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]);
21674   for (; i < nb; ++i) c[i] = b[i];
21675
21676   return function(t) {
21677     for (i = 0; i < na; ++i) c[i] = x[i](t);
21678     return c;
21679   };
21680 };
21681
21682 var date = function(a, b) {
21683   var d = new Date;
21684   return a = +a, b -= a, function(t) {
21685     return d.setTime(a + b * t), d;
21686   };
21687 };
21688
21689 var reinterpolate = function(a, b) {
21690   return a = +a, b -= a, function(t) {
21691     return a + b * t;
21692   };
21693 };
21694
21695 var object = function(a, b) {
21696   var i = {},
21697       c = {},
21698       k;
21699
21700   if (a === null || typeof a !== "object") a = {};
21701   if (b === null || typeof b !== "object") b = {};
21702
21703   for (k in b) {
21704     if (k in a) {
21705       i[k] = interpolateValue(a[k], b[k]);
21706     } else {
21707       c[k] = b[k];
21708     }
21709   }
21710
21711   return function(t) {
21712     for (k in i) c[k] = i[k](t);
21713     return c;
21714   };
21715 };
21716
21717 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
21718 var reB = new RegExp(reA.source, "g");
21719
21720 function zero(b) {
21721   return function() {
21722     return b;
21723   };
21724 }
21725
21726 function one(b) {
21727   return function(t) {
21728     return b(t) + "";
21729   };
21730 }
21731
21732 var interpolateString = function(a, b) {
21733   var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
21734       am, // current match in a
21735       bm, // current match in b
21736       bs, // string preceding current number in b, if any
21737       i = -1, // index in s
21738       s = [], // string constants and placeholders
21739       q = []; // number interpolators
21740
21741   // Coerce inputs to strings.
21742   a = a + "", b = b + "";
21743
21744   // Interpolate pairs of numbers in a & b.
21745   while ((am = reA.exec(a))
21746       && (bm = reB.exec(b))) {
21747     if ((bs = bm.index) > bi) { // a string precedes the next number in b
21748       bs = b.slice(bi, bs);
21749       if (s[i]) s[i] += bs; // coalesce with previous string
21750       else s[++i] = bs;
21751     }
21752     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
21753       if (s[i]) s[i] += bm; // coalesce with previous string
21754       else s[++i] = bm;
21755     } else { // interpolate non-matching numbers
21756       s[++i] = null;
21757       q.push({i: i, x: reinterpolate(am, bm)});
21758     }
21759     bi = reB.lastIndex;
21760   }
21761
21762   // Add remains of b.
21763   if (bi < b.length) {
21764     bs = b.slice(bi);
21765     if (s[i]) s[i] += bs; // coalesce with previous string
21766     else s[++i] = bs;
21767   }
21768
21769   // Special optimization for only a single match.
21770   // Otherwise, interpolate each of the numbers and rejoin the string.
21771   return s.length < 2 ? (q[0]
21772       ? one(q[0].x)
21773       : zero(b))
21774       : (b = q.length, function(t) {
21775           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
21776           return s.join("");
21777         });
21778 };
21779
21780 var interpolateValue = function(a, b) {
21781   var t = typeof b, c;
21782   return b == null || t === "boolean" ? constant$3(b)
21783       : (t === "number" ? reinterpolate
21784       : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
21785       : b instanceof color ? interpolateRgb
21786       : b instanceof Date ? date
21787       : Array.isArray(b) ? array$1
21788       : isNaN(b) ? object
21789       : reinterpolate)(a, b);
21790 };
21791
21792 var interpolateRound = function(a, b) {
21793   return a = +a, b -= a, function(t) {
21794     return Math.round(a + b * t);
21795   };
21796 };
21797
21798 var degrees = 180 / Math.PI;
21799
21800 var identity$2 = {
21801   translateX: 0,
21802   translateY: 0,
21803   rotate: 0,
21804   skewX: 0,
21805   scaleX: 1,
21806   scaleY: 1
21807 };
21808
21809 var decompose = function(a, b, c, d, e, f) {
21810   var scaleX, scaleY, skewX;
21811   if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
21812   if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
21813   if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
21814   if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
21815   return {
21816     translateX: e,
21817     translateY: f,
21818     rotate: Math.atan2(b, a) * degrees,
21819     skewX: Math.atan(skewX) * degrees,
21820     scaleX: scaleX,
21821     scaleY: scaleY
21822   };
21823 };
21824
21825 var cssNode;
21826 var cssRoot;
21827 var cssView;
21828 var svgNode;
21829
21830 function parseCss(value) {
21831   if (value === "none") return identity$2;
21832   if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
21833   cssNode.style.transform = value;
21834   value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
21835   cssRoot.removeChild(cssNode);
21836   value = value.slice(7, -1).split(",");
21837   return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
21838 }
21839
21840 function parseSvg(value) {
21841   if (value == null) return identity$2;
21842   if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
21843   svgNode.setAttribute("transform", value);
21844   if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
21845   value = value.matrix;
21846   return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
21847 }
21848
21849 function interpolateTransform(parse, pxComma, pxParen, degParen) {
21850
21851   function pop(s) {
21852     return s.length ? s.pop() + " " : "";
21853   }
21854
21855   function translate(xa, ya, xb, yb, s, q) {
21856     if (xa !== xb || ya !== yb) {
21857       var i = s.push("translate(", null, pxComma, null, pxParen);
21858       q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
21859     } else if (xb || yb) {
21860       s.push("translate(" + xb + pxComma + yb + pxParen);
21861     }
21862   }
21863
21864   function rotate(a, b, s, q) {
21865     if (a !== b) {
21866       if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
21867       q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)});
21868     } else if (b) {
21869       s.push(pop(s) + "rotate(" + b + degParen);
21870     }
21871   }
21872
21873   function skewX(a, b, s, q) {
21874     if (a !== b) {
21875       q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)});
21876     } else if (b) {
21877       s.push(pop(s) + "skewX(" + b + degParen);
21878     }
21879   }
21880
21881   function scale(xa, ya, xb, yb, s, q) {
21882     if (xa !== xb || ya !== yb) {
21883       var i = s.push(pop(s) + "scale(", null, ",", null, ")");
21884       q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)});
21885     } else if (xb !== 1 || yb !== 1) {
21886       s.push(pop(s) + "scale(" + xb + "," + yb + ")");
21887     }
21888   }
21889
21890   return function(a, b) {
21891     var s = [], // string constants and placeholders
21892         q = []; // number interpolators
21893     a = parse(a), b = parse(b);
21894     translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
21895     rotate(a.rotate, b.rotate, s, q);
21896     skewX(a.skewX, b.skewX, s, q);
21897     scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
21898     a = b = null; // gc
21899     return function(t) {
21900       var i = -1, n = q.length, o;
21901       while (++i < n) s[(o = q[i]).i] = o.x(t);
21902       return s.join("");
21903     };
21904   };
21905 }
21906
21907 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
21908 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
21909
21910 // p0 = [ux0, uy0, w0]
21911 // p1 = [ux1, uy1, w1]
21912
21913 function cubehelix$1(hue$$1) {
21914   return (function cubehelixGamma(y) {
21915     y = +y;
21916
21917     function cubehelix$$1(start, end) {
21918       var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
21919           s = nogamma(start.s, end.s),
21920           l = nogamma(start.l, end.l),
21921           opacity = nogamma(start.opacity, end.opacity);
21922       return function(t) {
21923         start.h = h(t);
21924         start.s = s(t);
21925         start.l = l(Math.pow(t, y));
21926         start.opacity = opacity(t);
21927         return start + "";
21928       };
21929     }
21930
21931     cubehelix$$1.gamma = cubehelixGamma;
21932
21933     return cubehelix$$1;
21934   })(1);
21935 }
21936
21937 cubehelix$1(hue);
21938 var cubehelixLong = cubehelix$1(nogamma);
21939
21940 var frame = 0;
21941 var timeout = 0;
21942 var interval = 0;
21943 var pokeDelay = 1000;
21944 var taskHead;
21945 var taskTail;
21946 var clockLast = 0;
21947 var clockNow = 0;
21948 var clockSkew = 0;
21949 var clock = typeof performance === "object" && performance.now ? performance : Date;
21950 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
21951
21952 function now() {
21953   return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
21954 }
21955
21956 function clearNow() {
21957   clockNow = 0;
21958 }
21959
21960 function Timer() {
21961   this._call =
21962   this._time =
21963   this._next = null;
21964 }
21965
21966 Timer.prototype = timer.prototype = {
21967   constructor: Timer,
21968   restart: function(callback, delay, time) {
21969     if (typeof callback !== "function") throw new TypeError("callback is not a function");
21970     time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
21971     if (!this._next && taskTail !== this) {
21972       if (taskTail) taskTail._next = this;
21973       else taskHead = this;
21974       taskTail = this;
21975     }
21976     this._call = callback;
21977     this._time = time;
21978     sleep();
21979   },
21980   stop: function() {
21981     if (this._call) {
21982       this._call = null;
21983       this._time = Infinity;
21984       sleep();
21985     }
21986   }
21987 };
21988
21989 function timer(callback, delay, time) {
21990   var t = new Timer;
21991   t.restart(callback, delay, time);
21992   return t;
21993 }
21994
21995 function timerFlush() {
21996   now(); // Get the current time, if not already set.
21997   ++frame; // Pretend we’ve set an alarm, if we haven’t already.
21998   var t = taskHead, e;
21999   while (t) {
22000     if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
22001     t = t._next;
22002   }
22003   --frame;
22004 }
22005
22006 function wake() {
22007   clockNow = (clockLast = clock.now()) + clockSkew;
22008   frame = timeout = 0;
22009   try {
22010     timerFlush();
22011   } finally {
22012     frame = 0;
22013     nap();
22014     clockNow = 0;
22015   }
22016 }
22017
22018 function poke() {
22019   var now = clock.now(), delay = now - clockLast;
22020   if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
22021 }
22022
22023 function nap() {
22024   var t0, t1 = taskHead, t2, time = Infinity;
22025   while (t1) {
22026     if (t1._call) {
22027       if (time > t1._time) time = t1._time;
22028       t0 = t1, t1 = t1._next;
22029     } else {
22030       t2 = t1._next, t1._next = null;
22031       t1 = t0 ? t0._next = t2 : taskHead = t2;
22032     }
22033   }
22034   taskTail = t0;
22035   sleep(time);
22036 }
22037
22038 function sleep(time) {
22039   if (frame) return; // Soonest alarm already set, or will be.
22040   if (timeout) timeout = clearTimeout(timeout);
22041   var delay = time - clockNow;
22042   if (delay > 24) {
22043     if (time < Infinity) timeout = setTimeout(wake, delay);
22044     if (interval) interval = clearInterval(interval);
22045   } else {
22046     if (!interval) interval = setInterval(poke, pokeDelay);
22047     frame = 1, setFrame(wake);
22048   }
22049 }
22050
22051 var timeout$1 = function(callback, delay, time) {
22052   var t = new Timer;
22053   delay = delay == null ? 0 : +delay;
22054   t.restart(function(elapsed) {
22055     t.stop();
22056     callback(elapsed + delay);
22057   }, delay, time);
22058   return t;
22059 };
22060
22061 var emptyOn = dispatch("start", "end", "interrupt");
22062 var emptyTween = [];
22063
22064 var CREATED = 0;
22065 var SCHEDULED = 1;
22066 var STARTING = 2;
22067 var STARTED = 3;
22068 var RUNNING = 4;
22069 var ENDING = 5;
22070 var ENDED = 6;
22071
22072 var schedule = function(node, name, id, index, group, timing) {
22073   var schedules = node.__transition;
22074   if (!schedules) node.__transition = {};
22075   else if (id in schedules) return;
22076   create(node, id, {
22077     name: name,
22078     index: index, // For context during callback.
22079     group: group, // For context during callback.
22080     on: emptyOn,
22081     tween: emptyTween,
22082     time: timing.time,
22083     delay: timing.delay,
22084     duration: timing.duration,
22085     ease: timing.ease,
22086     timer: null,
22087     state: CREATED
22088   });
22089 };
22090
22091 function init(node, id) {
22092   var schedule = node.__transition;
22093   if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
22094   return schedule;
22095 }
22096
22097 function set$1(node, id) {
22098   var schedule = node.__transition;
22099   if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
22100   return schedule;
22101 }
22102
22103 function get$1(node, id) {
22104   var schedule = node.__transition;
22105   if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
22106   return schedule;
22107 }
22108
22109 function create(node, id, self) {
22110   var schedules = node.__transition,
22111       tween;
22112
22113   // Initialize the self timer when the transition is created.
22114   // Note the actual delay is not known until the first callback!
22115   schedules[id] = self;
22116   self.timer = timer(schedule, 0, self.time);
22117
22118   function schedule(elapsed) {
22119     self.state = SCHEDULED;
22120     self.timer.restart(start, self.delay, self.time);
22121
22122     // If the elapsed delay is less than our first sleep, start immediately.
22123     if (self.delay <= elapsed) start(elapsed - self.delay);
22124   }
22125
22126   function start(elapsed) {
22127     var i, j, n, o;
22128
22129     // If the state is not SCHEDULED, then we previously errored on start.
22130     if (self.state !== SCHEDULED) return stop();
22131
22132     for (i in schedules) {
22133       o = schedules[i];
22134       if (o.name !== self.name) continue;
22135
22136       // While this element already has a starting transition during this frame,
22137       // defer starting an interrupting transition until that transition has a
22138       // chance to tick (and possibly end); see d3/d3-transition#54!
22139       if (o.state === STARTED) return timeout$1(start);
22140
22141       // Interrupt the active transition, if any.
22142       // Dispatch the interrupt event.
22143       if (o.state === RUNNING) {
22144         o.state = ENDED;
22145         o.timer.stop();
22146         o.on.call("interrupt", node, node.__data__, o.index, o.group);
22147         delete schedules[i];
22148       }
22149
22150       // Cancel any pre-empted transitions. No interrupt event is dispatched
22151       // because the cancelled transitions never started. Note that this also
22152       // removes this transition from the pending list!
22153       else if (+i < id) {
22154         o.state = ENDED;
22155         o.timer.stop();
22156         delete schedules[i];
22157       }
22158     }
22159
22160     // Defer the first tick to end of the current frame; see d3/d3#1576.
22161     // Note the transition may be canceled after start and before the first tick!
22162     // Note this must be scheduled before the start event; see d3/d3-transition#16!
22163     // Assuming this is successful, subsequent callbacks go straight to tick.
22164     timeout$1(function() {
22165       if (self.state === STARTED) {
22166         self.state = RUNNING;
22167         self.timer.restart(tick, self.delay, self.time);
22168         tick(elapsed);
22169       }
22170     });
22171
22172     // Dispatch the start event.
22173     // Note this must be done before the tween are initialized.
22174     self.state = STARTING;
22175     self.on.call("start", node, node.__data__, self.index, self.group);
22176     if (self.state !== STARTING) return; // interrupted
22177     self.state = STARTED;
22178
22179     // Initialize the tween, deleting null tween.
22180     tween = new Array(n = self.tween.length);
22181     for (i = 0, j = -1; i < n; ++i) {
22182       if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
22183         tween[++j] = o;
22184       }
22185     }
22186     tween.length = j + 1;
22187   }
22188
22189   function tick(elapsed) {
22190     var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
22191         i = -1,
22192         n = tween.length;
22193
22194     while (++i < n) {
22195       tween[i].call(null, t);
22196     }
22197
22198     // Dispatch the end event.
22199     if (self.state === ENDING) {
22200       self.on.call("end", node, node.__data__, self.index, self.group);
22201       stop();
22202     }
22203   }
22204
22205   function stop() {
22206     self.state = ENDED;
22207     self.timer.stop();
22208     delete schedules[id];
22209     for (var i in schedules) return; // eslint-disable-line no-unused-vars
22210     delete node.__transition;
22211   }
22212 }
22213
22214 var interrupt = function(node, name) {
22215   var schedules = node.__transition,
22216       schedule,
22217       active,
22218       empty = true,
22219       i;
22220
22221   if (!schedules) return;
22222
22223   name = name == null ? null : name + "";
22224
22225   for (i in schedules) {
22226     if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
22227     active = schedule.state > STARTING && schedule.state < ENDING;
22228     schedule.state = ENDED;
22229     schedule.timer.stop();
22230     if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
22231     delete schedules[i];
22232   }
22233
22234   if (empty) delete node.__transition;
22235 };
22236
22237 var selection_interrupt = function(name) {
22238   return this.each(function() {
22239     interrupt(this, name);
22240   });
22241 };
22242
22243 function tweenRemove(id, name) {
22244   var tween0, tween1;
22245   return function() {
22246     var schedule = set$1(this, id),
22247         tween = schedule.tween;
22248
22249     // If this node shared tween with the previous node,
22250     // just assign the updated shared tween and we’re done!
22251     // Otherwise, copy-on-write.
22252     if (tween !== tween0) {
22253       tween1 = tween0 = tween;
22254       for (var i = 0, n = tween1.length; i < n; ++i) {
22255         if (tween1[i].name === name) {
22256           tween1 = tween1.slice();
22257           tween1.splice(i, 1);
22258           break;
22259         }
22260       }
22261     }
22262
22263     schedule.tween = tween1;
22264   };
22265 }
22266
22267 function tweenFunction(id, name, value) {
22268   var tween0, tween1;
22269   if (typeof value !== "function") throw new Error;
22270   return function() {
22271     var schedule = set$1(this, id),
22272         tween = schedule.tween;
22273
22274     // If this node shared tween with the previous node,
22275     // just assign the updated shared tween and we’re done!
22276     // Otherwise, copy-on-write.
22277     if (tween !== tween0) {
22278       tween1 = (tween0 = tween).slice();
22279       for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
22280         if (tween1[i].name === name) {
22281           tween1[i] = t;
22282           break;
22283         }
22284       }
22285       if (i === n) tween1.push(t);
22286     }
22287
22288     schedule.tween = tween1;
22289   };
22290 }
22291
22292 var transition_tween = function(name, value) {
22293   var id = this._id;
22294
22295   name += "";
22296
22297   if (arguments.length < 2) {
22298     var tween = get$1(this.node(), id).tween;
22299     for (var i = 0, n = tween.length, t; i < n; ++i) {
22300       if ((t = tween[i]).name === name) {
22301         return t.value;
22302       }
22303     }
22304     return null;
22305   }
22306
22307   return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
22308 };
22309
22310 function tweenValue(transition, name, value) {
22311   var id = transition._id;
22312
22313   transition.each(function() {
22314     var schedule = set$1(this, id);
22315     (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
22316   });
22317
22318   return function(node) {
22319     return get$1(node, id).value[name];
22320   };
22321 }
22322
22323 var interpolate$$1 = function(a, b) {
22324   var c;
22325   return (typeof b === "number" ? reinterpolate
22326       : b instanceof color ? interpolateRgb
22327       : (c = color(b)) ? (b = c, interpolateRgb)
22328       : interpolateString)(a, b);
22329 };
22330
22331 function attrRemove$1(name) {
22332   return function() {
22333     this.removeAttribute(name);
22334   };
22335 }
22336
22337 function attrRemoveNS$1(fullname) {
22338   return function() {
22339     this.removeAttributeNS(fullname.space, fullname.local);
22340   };
22341 }
22342
22343 function attrConstant$1(name, interpolate$$1, value1) {
22344   var value00,
22345       interpolate0;
22346   return function() {
22347     var value0 = this.getAttribute(name);
22348     return value0 === value1 ? null
22349         : value0 === value00 ? interpolate0
22350         : interpolate0 = interpolate$$1(value00 = value0, value1);
22351   };
22352 }
22353
22354 function attrConstantNS$1(fullname, interpolate$$1, value1) {
22355   var value00,
22356       interpolate0;
22357   return function() {
22358     var value0 = this.getAttributeNS(fullname.space, fullname.local);
22359     return value0 === value1 ? null
22360         : value0 === value00 ? interpolate0
22361         : interpolate0 = interpolate$$1(value00 = value0, value1);
22362   };
22363 }
22364
22365 function attrFunction$1(name, interpolate$$1, value) {
22366   var value00,
22367       value10,
22368       interpolate0;
22369   return function() {
22370     var value0, value1 = value(this);
22371     if (value1 == null) return void this.removeAttribute(name);
22372     value0 = this.getAttribute(name);
22373     return value0 === value1 ? null
22374         : value0 === value00 && value1 === value10 ? interpolate0
22375         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22376   };
22377 }
22378
22379 function attrFunctionNS$1(fullname, interpolate$$1, value) {
22380   var value00,
22381       value10,
22382       interpolate0;
22383   return function() {
22384     var value0, value1 = value(this);
22385     if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
22386     value0 = this.getAttributeNS(fullname.space, fullname.local);
22387     return value0 === value1 ? null
22388         : value0 === value00 && value1 === value10 ? interpolate0
22389         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
22390   };
22391 }
22392
22393 var transition_attr = function(name, value) {
22394   var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$$1;
22395   return this.attrTween(name, typeof value === "function"
22396       ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
22397       : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
22398       : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value));
22399 };
22400
22401 function attrTweenNS(fullname, value) {
22402   function tween() {
22403     var node = this, i = value.apply(node, arguments);
22404     return i && function(t) {
22405       node.setAttributeNS(fullname.space, fullname.local, i(t));
22406     };
22407   }
22408   tween._value = value;
22409   return tween;
22410 }
22411
22412 function attrTween(name, value) {
22413   function tween() {
22414     var node = this, i = value.apply(node, arguments);
22415     return i && function(t) {
22416       node.setAttribute(name, i(t));
22417     };
22418   }
22419   tween._value = value;
22420   return tween;
22421 }
22422
22423 var transition_attrTween = function(name, value) {
22424   var key = "attr." + name;
22425   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22426   if (value == null) return this.tween(key, null);
22427   if (typeof value !== "function") throw new Error;
22428   var fullname = namespace(name);
22429   return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
22430 };
22431
22432 function delayFunction(id, value) {
22433   return function() {
22434     init(this, id).delay = +value.apply(this, arguments);
22435   };
22436 }
22437
22438 function delayConstant(id, value) {
22439   return value = +value, function() {
22440     init(this, id).delay = value;
22441   };
22442 }
22443
22444 var transition_delay = function(value) {
22445   var id = this._id;
22446
22447   return arguments.length
22448       ? this.each((typeof value === "function"
22449           ? delayFunction
22450           : delayConstant)(id, value))
22451       : get$1(this.node(), id).delay;
22452 };
22453
22454 function durationFunction(id, value) {
22455   return function() {
22456     set$1(this, id).duration = +value.apply(this, arguments);
22457   };
22458 }
22459
22460 function durationConstant(id, value) {
22461   return value = +value, function() {
22462     set$1(this, id).duration = value;
22463   };
22464 }
22465
22466 var transition_duration = function(value) {
22467   var id = this._id;
22468
22469   return arguments.length
22470       ? this.each((typeof value === "function"
22471           ? durationFunction
22472           : durationConstant)(id, value))
22473       : get$1(this.node(), id).duration;
22474 };
22475
22476 function easeConstant(id, value) {
22477   if (typeof value !== "function") throw new Error;
22478   return function() {
22479     set$1(this, id).ease = value;
22480   };
22481 }
22482
22483 var transition_ease = function(value) {
22484   var id = this._id;
22485
22486   return arguments.length
22487       ? this.each(easeConstant(id, value))
22488       : get$1(this.node(), id).ease;
22489 };
22490
22491 var transition_filter = function(match) {
22492   if (typeof match !== "function") match = matcher$1(match);
22493
22494   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22495     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
22496       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
22497         subgroup.push(node);
22498       }
22499     }
22500   }
22501
22502   return new Transition(subgroups, this._parents, this._name, this._id);
22503 };
22504
22505 var transition_merge = function(transition) {
22506   if (transition._id !== this._id) throw new Error;
22507
22508   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) {
22509     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
22510       if (node = group0[i] || group1[i]) {
22511         merge[i] = node;
22512       }
22513     }
22514   }
22515
22516   for (; j < m0; ++j) {
22517     merges[j] = groups0[j];
22518   }
22519
22520   return new Transition(merges, this._parents, this._name, this._id);
22521 };
22522
22523 function start(name) {
22524   return (name + "").trim().split(/^|\s+/).every(function(t) {
22525     var i = t.indexOf(".");
22526     if (i >= 0) t = t.slice(0, i);
22527     return !t || t === "start";
22528   });
22529 }
22530
22531 function onFunction(id, name, listener) {
22532   var on0, on1, sit = start(name) ? init : set$1;
22533   return function() {
22534     var schedule = sit(this, id),
22535         on = schedule.on;
22536
22537     // If this node shared a dispatch with the previous node,
22538     // just assign the updated shared dispatch and we’re done!
22539     // Otherwise, copy-on-write.
22540     if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
22541
22542     schedule.on = on1;
22543   };
22544 }
22545
22546 var transition_on = function(name, listener) {
22547   var id = this._id;
22548
22549   return arguments.length < 2
22550       ? get$1(this.node(), id).on.on(name)
22551       : this.each(onFunction(id, name, listener));
22552 };
22553
22554 function removeFunction(id) {
22555   return function() {
22556     var parent = this.parentNode;
22557     for (var i in this.__transition) if (+i !== id) return;
22558     if (parent) parent.removeChild(this);
22559   };
22560 }
22561
22562 var transition_remove = function() {
22563   return this.on("end.remove", removeFunction(this._id));
22564 };
22565
22566 var transition_select = function(select$$1) {
22567   var name = this._name,
22568       id = this._id;
22569
22570   if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
22571
22572   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
22573     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
22574       if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
22575         if ("__data__" in node) subnode.__data__ = node.__data__;
22576         subgroup[i] = subnode;
22577         schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
22578       }
22579     }
22580   }
22581
22582   return new Transition(subgroups, this._parents, name, id);
22583 };
22584
22585 var transition_selectAll = function(select$$1) {
22586   var name = this._name,
22587       id = this._id;
22588
22589   if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
22590
22591   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
22592     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
22593       if (node = group[i]) {
22594         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) {
22595           if (child = children[k]) {
22596             schedule(child, name, id, k, children, inherit);
22597           }
22598         }
22599         subgroups.push(children);
22600         parents.push(node);
22601       }
22602     }
22603   }
22604
22605   return new Transition(subgroups, parents, name, id);
22606 };
22607
22608 var Selection$1 = selection.prototype.constructor;
22609
22610 var transition_selection = function() {
22611   return new Selection$1(this._groups, this._parents);
22612 };
22613
22614 function styleRemove$1(name, interpolate$$2) {
22615   var value00,
22616       value10,
22617       interpolate0;
22618   return function() {
22619     var style = window$1(this).getComputedStyle(this, null),
22620         value0 = style.getPropertyValue(name),
22621         value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22622     return value0 === value1 ? null
22623         : value0 === value00 && value1 === value10 ? interpolate0
22624         : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22625   };
22626 }
22627
22628 function styleRemoveEnd(name) {
22629   return function() {
22630     this.style.removeProperty(name);
22631   };
22632 }
22633
22634 function styleConstant$1(name, interpolate$$2, value1) {
22635   var value00,
22636       interpolate0;
22637   return function() {
22638     var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
22639     return value0 === value1 ? null
22640         : value0 === value00 ? interpolate0
22641         : interpolate0 = interpolate$$2(value00 = value0, value1);
22642   };
22643 }
22644
22645 function styleFunction$1(name, interpolate$$2, value) {
22646   var value00,
22647       value10,
22648       interpolate0;
22649   return function() {
22650     var style = window$1(this).getComputedStyle(this, null),
22651         value0 = style.getPropertyValue(name),
22652         value1 = value(this);
22653     if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
22654     return value0 === value1 ? null
22655         : value0 === value00 && value1 === value10 ? interpolate0
22656         : interpolate0 = interpolate$$2(value00 = value0, value10 = value1);
22657   };
22658 }
22659
22660 var transition_style = function(name, value, priority) {
22661   var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$$1;
22662   return value == null ? this
22663           .styleTween(name, styleRemove$1(name, i))
22664           .on("end.style." + name, styleRemoveEnd(name))
22665       : this.styleTween(name, typeof value === "function"
22666           ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
22667           : styleConstant$1(name, i, value), priority);
22668 };
22669
22670 function styleTween(name, value, priority) {
22671   function tween() {
22672     var node = this, i = value.apply(node, arguments);
22673     return i && function(t) {
22674       node.style.setProperty(name, i(t), priority);
22675     };
22676   }
22677   tween._value = value;
22678   return tween;
22679 }
22680
22681 var transition_styleTween = function(name, value, priority) {
22682   var key = "style." + (name += "");
22683   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
22684   if (value == null) return this.tween(key, null);
22685   if (typeof value !== "function") throw new Error;
22686   return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
22687 };
22688
22689 function textConstant$1(value) {
22690   return function() {
22691     this.textContent = value;
22692   };
22693 }
22694
22695 function textFunction$1(value) {
22696   return function() {
22697     var value1 = value(this);
22698     this.textContent = value1 == null ? "" : value1;
22699   };
22700 }
22701
22702 var transition_text = function(value) {
22703   return this.tween("text", typeof value === "function"
22704       ? textFunction$1(tweenValue(this, "text", value))
22705       : textConstant$1(value == null ? "" : value + ""));
22706 };
22707
22708 var transition_transition = function() {
22709   var name = this._name,
22710       id0 = this._id,
22711       id1 = newId();
22712
22713   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
22714     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
22715       if (node = group[i]) {
22716         var inherit = get$1(node, id0);
22717         schedule(node, name, id1, i, group, {
22718           time: inherit.time + inherit.delay + inherit.duration,
22719           delay: 0,
22720           duration: inherit.duration,
22721           ease: inherit.ease
22722         });
22723       }
22724     }
22725   }
22726
22727   return new Transition(groups, this._parents, name, id1);
22728 };
22729
22730 var id = 0;
22731
22732 function Transition(groups, parents, name, id) {
22733   this._groups = groups;
22734   this._parents = parents;
22735   this._name = name;
22736   this._id = id;
22737 }
22738
22739 function transition(name) {
22740   return selection().transition(name);
22741 }
22742
22743 function newId() {
22744   return ++id;
22745 }
22746
22747 var selection_prototype = selection.prototype;
22748
22749 Transition.prototype = transition.prototype = {
22750   constructor: Transition,
22751   select: transition_select,
22752   selectAll: transition_selectAll,
22753   filter: transition_filter,
22754   merge: transition_merge,
22755   selection: transition_selection,
22756   transition: transition_transition,
22757   call: selection_prototype.call,
22758   nodes: selection_prototype.nodes,
22759   node: selection_prototype.node,
22760   size: selection_prototype.size,
22761   empty: selection_prototype.empty,
22762   each: selection_prototype.each,
22763   on: transition_on,
22764   attr: transition_attr,
22765   attrTween: transition_attrTween,
22766   style: transition_style,
22767   styleTween: transition_styleTween,
22768   text: transition_text,
22769   remove: transition_remove,
22770   tween: transition_tween,
22771   delay: transition_delay,
22772   duration: transition_duration,
22773   ease: transition_ease
22774 };
22775
22776 function linear$1(t) {
22777   return +t;
22778 }
22779
22780 function quadIn(t) {
22781   return t * t;
22782 }
22783
22784 function quadOut(t) {
22785   return t * (2 - t);
22786 }
22787
22788 function quadInOut(t) {
22789   return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
22790 }
22791
22792 function cubicIn(t) {
22793   return t * t * t;
22794 }
22795
22796 function cubicOut(t) {
22797   return --t * t * t + 1;
22798 }
22799
22800 function cubicInOut(t) {
22801   return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
22802 }
22803
22804 var exponent = 3;
22805
22806 var polyIn = (function custom(e) {
22807   e = +e;
22808
22809   function polyIn(t) {
22810     return Math.pow(t, e);
22811   }
22812
22813   polyIn.exponent = custom;
22814
22815   return polyIn;
22816 })(exponent);
22817
22818 var polyOut = (function custom(e) {
22819   e = +e;
22820
22821   function polyOut(t) {
22822     return 1 - Math.pow(1 - t, e);
22823   }
22824
22825   polyOut.exponent = custom;
22826
22827   return polyOut;
22828 })(exponent);
22829
22830 var polyInOut = (function custom(e) {
22831   e = +e;
22832
22833   function polyInOut(t) {
22834     return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
22835   }
22836
22837   polyInOut.exponent = custom;
22838
22839   return polyInOut;
22840 })(exponent);
22841
22842 var pi = Math.PI;
22843 var halfPi = pi / 2;
22844
22845 function sinIn(t) {
22846   return 1 - Math.cos(t * halfPi);
22847 }
22848
22849 function sinOut(t) {
22850   return Math.sin(t * halfPi);
22851 }
22852
22853 function sinInOut(t) {
22854   return (1 - Math.cos(pi * t)) / 2;
22855 }
22856
22857 function expIn(t) {
22858   return Math.pow(2, 10 * t - 10);
22859 }
22860
22861 function expOut(t) {
22862   return 1 - Math.pow(2, -10 * t);
22863 }
22864
22865 function expInOut(t) {
22866   return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
22867 }
22868
22869 function circleIn(t) {
22870   return 1 - Math.sqrt(1 - t * t);
22871 }
22872
22873 function circleOut(t) {
22874   return Math.sqrt(1 - --t * t);
22875 }
22876
22877 function circleInOut(t) {
22878   return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
22879 }
22880
22881 var b1 = 4 / 11;
22882 var b2 = 6 / 11;
22883 var b3 = 8 / 11;
22884 var b4 = 3 / 4;
22885 var b5 = 9 / 11;
22886 var b6 = 10 / 11;
22887 var b7 = 15 / 16;
22888 var b8 = 21 / 22;
22889 var b9 = 63 / 64;
22890 var b0 = 1 / b1 / b1;
22891
22892 function bounceIn(t) {
22893   return 1 - bounceOut(1 - t);
22894 }
22895
22896 function bounceOut(t) {
22897   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;
22898 }
22899
22900 function bounceInOut(t) {
22901   return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
22902 }
22903
22904 var overshoot = 1.70158;
22905
22906 var backIn = (function custom(s) {
22907   s = +s;
22908
22909   function backIn(t) {
22910     return t * t * ((s + 1) * t - s);
22911   }
22912
22913   backIn.overshoot = custom;
22914
22915   return backIn;
22916 })(overshoot);
22917
22918 var backOut = (function custom(s) {
22919   s = +s;
22920
22921   function backOut(t) {
22922     return --t * t * ((s + 1) * t + s) + 1;
22923   }
22924
22925   backOut.overshoot = custom;
22926
22927   return backOut;
22928 })(overshoot);
22929
22930 var backInOut = (function custom(s) {
22931   s = +s;
22932
22933   function backInOut(t) {
22934     return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
22935   }
22936
22937   backInOut.overshoot = custom;
22938
22939   return backInOut;
22940 })(overshoot);
22941
22942 var tau = 2 * Math.PI;
22943 var amplitude = 1;
22944 var period = 0.3;
22945
22946 var elasticIn = (function custom(a, p) {
22947   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
22948
22949   function elasticIn(t) {
22950     return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
22951   }
22952
22953   elasticIn.amplitude = function(a) { return custom(a, p * tau); };
22954   elasticIn.period = function(p) { return custom(a, p); };
22955
22956   return elasticIn;
22957 })(amplitude, period);
22958
22959 var elasticOut = (function custom(a, p) {
22960   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
22961
22962   function elasticOut(t) {
22963     return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
22964   }
22965
22966   elasticOut.amplitude = function(a) { return custom(a, p * tau); };
22967   elasticOut.period = function(p) { return custom(a, p); };
22968
22969   return elasticOut;
22970 })(amplitude, period);
22971
22972 var elasticInOut = (function custom(a, p) {
22973   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
22974
22975   function elasticInOut(t) {
22976     return ((t = t * 2 - 1) < 0
22977         ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
22978         : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
22979   }
22980
22981   elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
22982   elasticInOut.period = function(p) { return custom(a, p); };
22983
22984   return elasticInOut;
22985 })(amplitude, period);
22986
22987 var defaultTiming = {
22988   time: null, // Set on use.
22989   delay: 0,
22990   duration: 250,
22991   ease: cubicInOut
22992 };
22993
22994 function inherit(node, id) {
22995   var timing;
22996   while (!(timing = node.__transition) || !(timing = timing[id])) {
22997     if (!(node = node.parentNode)) {
22998       return defaultTiming.time = now(), defaultTiming;
22999     }
23000   }
23001   return timing;
23002 }
23003
23004 var selection_transition = function(name) {
23005   var id,
23006       timing;
23007
23008   if (name instanceof Transition) {
23009     id = name._id, name = name._name;
23010   } else {
23011     id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
23012   }
23013
23014   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
23015     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
23016       if (node = group[i]) {
23017         schedule(node, name, id, i, group, timing || inherit(node, id));
23018       }
23019     }
23020   }
23021
23022   return new Transition(groups, this._parents, name, id);
23023 };
23024
23025 selection.prototype.interrupt = selection_interrupt;
23026 selection.prototype.transition = selection_transition;
23027
23028 var root$1 = [null];
23029
23030 var active = function(node, name) {
23031   var schedules = node.__transition,
23032       schedule,
23033       i;
23034
23035   if (schedules) {
23036     name = name == null ? null : name + "";
23037     for (i in schedules) {
23038       if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
23039         return new Transition([[node]], root$1, name, +i);
23040       }
23041     }
23042   }
23043
23044   return null;
23045 };
23046
23047 var constant$4 = function(x) {
23048   return function() {
23049     return x;
23050   };
23051 };
23052
23053 var BrushEvent = function(target, type, selection) {
23054   this.target = target;
23055   this.type = type;
23056   this.selection = selection;
23057 };
23058
23059 function nopropagation$1() {
23060   event.stopImmediatePropagation();
23061 }
23062
23063 var noevent$1 = function() {
23064   event.preventDefault();
23065   event.stopImmediatePropagation();
23066 };
23067
23068 var MODE_DRAG = {name: "drag"};
23069 var MODE_SPACE = {name: "space"};
23070 var MODE_HANDLE = {name: "handle"};
23071 var MODE_CENTER = {name: "center"};
23072
23073 var X = {
23074   name: "x",
23075   handles: ["e", "w"].map(type$2),
23076   input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
23077   output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
23078 };
23079
23080 var Y = {
23081   name: "y",
23082   handles: ["n", "s"].map(type$2),
23083   input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
23084   output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
23085 };
23086
23087 var XY = {
23088   name: "xy",
23089   handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$2),
23090   input: function(xy) { return xy; },
23091   output: function(xy) { return xy; }
23092 };
23093
23094 var cursors = {
23095   overlay: "crosshair",
23096   selection: "move",
23097   n: "ns-resize",
23098   e: "ew-resize",
23099   s: "ns-resize",
23100   w: "ew-resize",
23101   nw: "nwse-resize",
23102   ne: "nesw-resize",
23103   se: "nwse-resize",
23104   sw: "nesw-resize"
23105 };
23106
23107 var flipX = {
23108   e: "w",
23109   w: "e",
23110   nw: "ne",
23111   ne: "nw",
23112   se: "sw",
23113   sw: "se"
23114 };
23115
23116 var flipY = {
23117   n: "s",
23118   s: "n",
23119   nw: "sw",
23120   ne: "se",
23121   se: "ne",
23122   sw: "nw"
23123 };
23124
23125 var signsX = {
23126   overlay: +1,
23127   selection: +1,
23128   n: null,
23129   e: +1,
23130   s: null,
23131   w: -1,
23132   nw: -1,
23133   ne: +1,
23134   se: +1,
23135   sw: -1
23136 };
23137
23138 var signsY = {
23139   overlay: +1,
23140   selection: +1,
23141   n: -1,
23142   e: null,
23143   s: +1,
23144   w: null,
23145   nw: -1,
23146   ne: -1,
23147   se: +1,
23148   sw: +1
23149 };
23150
23151 function type$2(t) {
23152   return {type: t};
23153 }
23154
23155 // Ignore right-click, since that should open the context menu.
23156 function defaultFilter() {
23157   return !event.button;
23158 }
23159
23160 function defaultExtent() {
23161   var svg = this.ownerSVGElement || this;
23162   return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
23163 }
23164
23165 // Like d3.local, but with the name “__brush” rather than auto-generated.
23166 function local$$1(node) {
23167   while (!node.__brush) if (!(node = node.parentNode)) return;
23168   return node.__brush;
23169 }
23170
23171 function empty(extent) {
23172   return extent[0][0] === extent[1][0]
23173       || extent[0][1] === extent[1][1];
23174 }
23175
23176 function brushSelection(node) {
23177   var state = node.__brush;
23178   return state ? state.dim.output(state.selection) : null;
23179 }
23180
23181 function brushX() {
23182   return brush$1(X);
23183 }
23184
23185 function brushY() {
23186   return brush$1(Y);
23187 }
23188
23189 var brush = function() {
23190   return brush$1(XY);
23191 };
23192
23193 function brush$1(dim) {
23194   var extent = defaultExtent,
23195       filter = defaultFilter,
23196       listeners = dispatch(brush, "start", "brush", "end"),
23197       handleSize = 6,
23198       touchending;
23199
23200   function brush(group) {
23201     var overlay = group
23202         .property("__brush", initialize)
23203       .selectAll(".overlay")
23204       .data([type$2("overlay")]);
23205
23206     overlay.enter().append("rect")
23207         .attr("class", "overlay")
23208         .attr("pointer-events", "all")
23209         .attr("cursor", cursors.overlay)
23210       .merge(overlay)
23211         .each(function() {
23212           var extent = local$$1(this).extent;
23213           select(this)
23214               .attr("x", extent[0][0])
23215               .attr("y", extent[0][1])
23216               .attr("width", extent[1][0] - extent[0][0])
23217               .attr("height", extent[1][1] - extent[0][1]);
23218         });
23219
23220     group.selectAll(".selection")
23221       .data([type$2("selection")])
23222       .enter().append("rect")
23223         .attr("class", "selection")
23224         .attr("cursor", cursors.selection)
23225         .attr("fill", "#777")
23226         .attr("fill-opacity", 0.3)
23227         .attr("stroke", "#fff")
23228         .attr("shape-rendering", "crispEdges");
23229
23230     var handle = group.selectAll(".handle")
23231       .data(dim.handles, function(d) { return d.type; });
23232
23233     handle.exit().remove();
23234
23235     handle.enter().append("rect")
23236         .attr("class", function(d) { return "handle handle--" + d.type; })
23237         .attr("cursor", function(d) { return cursors[d.type]; });
23238
23239     group
23240         .each(redraw)
23241         .attr("fill", "none")
23242         .attr("pointer-events", "all")
23243         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
23244         .on("mousedown.brush touchstart.brush", started);
23245   }
23246
23247   brush.move = function(group, selection$$1) {
23248     if (group.selection) {
23249       group
23250           .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
23251           .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
23252           .tween("brush", function() {
23253             var that = this,
23254                 state = that.__brush,
23255                 emit = emitter(that, arguments),
23256                 selection0 = state.selection,
23257                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
23258                 i = interpolateValue(selection0, selection1);
23259
23260             function tween(t) {
23261               state.selection = t === 1 && empty(selection1) ? null : i(t);
23262               redraw.call(that);
23263               emit.brush();
23264             }
23265
23266             return selection0 && selection1 ? tween : tween(1);
23267           });
23268     } else {
23269       group
23270           .each(function() {
23271             var that = this,
23272                 args = arguments,
23273                 state = that.__brush,
23274                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
23275                 emit = emitter(that, args).beforestart();
23276
23277             interrupt(that);
23278             state.selection = selection1 == null || empty(selection1) ? null : selection1;
23279             redraw.call(that);
23280             emit.start().brush().end();
23281           });
23282     }
23283   };
23284
23285   function redraw() {
23286     var group = select(this),
23287         selection$$1 = local$$1(this).selection;
23288
23289     if (selection$$1) {
23290       group.selectAll(".selection")
23291           .style("display", null)
23292           .attr("x", selection$$1[0][0])
23293           .attr("y", selection$$1[0][1])
23294           .attr("width", selection$$1[1][0] - selection$$1[0][0])
23295           .attr("height", selection$$1[1][1] - selection$$1[0][1]);
23296
23297       group.selectAll(".handle")
23298           .style("display", null)
23299           .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
23300           .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
23301           .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
23302           .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
23303     }
23304
23305     else {
23306       group.selectAll(".selection,.handle")
23307           .style("display", "none")
23308           .attr("x", null)
23309           .attr("y", null)
23310           .attr("width", null)
23311           .attr("height", null);
23312     }
23313   }
23314
23315   function emitter(that, args) {
23316     return that.__brush.emitter || new Emitter(that, args);
23317   }
23318
23319   function Emitter(that, args) {
23320     this.that = that;
23321     this.args = args;
23322     this.state = that.__brush;
23323     this.active = 0;
23324   }
23325
23326   Emitter.prototype = {
23327     beforestart: function() {
23328       if (++this.active === 1) this.state.emitter = this, this.starting = true;
23329       return this;
23330     },
23331     start: function() {
23332       if (this.starting) this.starting = false, this.emit("start");
23333       return this;
23334     },
23335     brush: function() {
23336       this.emit("brush");
23337       return this;
23338     },
23339     end: function() {
23340       if (--this.active === 0) delete this.state.emitter, this.emit("end");
23341       return this;
23342     },
23343     emit: function(type) {
23344       customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
23345     }
23346   };
23347
23348   function started() {
23349     if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$1(); }
23350     else if (touchending) return;
23351     if (!filter.apply(this, arguments)) return;
23352
23353     var that = this,
23354         type = event.target.__data__.type,
23355         mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
23356         signX = dim === Y ? null : signsX[type],
23357         signY = dim === X ? null : signsY[type],
23358         state = local$$1(that),
23359         extent = state.extent,
23360         selection$$1 = state.selection,
23361         W = extent[0][0], w0, w1,
23362         N = extent[0][1], n0, n1,
23363         E = extent[1][0], e0, e1,
23364         S = extent[1][1], s0, s1,
23365         dx,
23366         dy,
23367         moving,
23368         shifting = signX && signY && event.shiftKey,
23369         lockX,
23370         lockY,
23371         point0 = mouse(that),
23372         point = point0,
23373         emit = emitter(that, arguments).beforestart();
23374
23375     if (type === "overlay") {
23376       state.selection = selection$$1 = [
23377         [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
23378         [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
23379       ];
23380     } else {
23381       w0 = selection$$1[0][0];
23382       n0 = selection$$1[0][1];
23383       e0 = selection$$1[1][0];
23384       s0 = selection$$1[1][1];
23385     }
23386
23387     w1 = w0;
23388     n1 = n0;
23389     e1 = e0;
23390     s1 = s0;
23391
23392     var group = select(that)
23393         .attr("pointer-events", "none");
23394
23395     var overlay = group.selectAll(".overlay")
23396         .attr("cursor", cursors[type]);
23397
23398     if (event.touches) {
23399       group
23400           .on("touchmove.brush", moved, true)
23401           .on("touchend.brush touchcancel.brush", ended, true);
23402     } else {
23403       var view = select(event.view)
23404           .on("keydown.brush", keydowned, true)
23405           .on("keyup.brush", keyupped, true)
23406           .on("mousemove.brush", moved, true)
23407           .on("mouseup.brush", ended, true);
23408
23409       dragDisable(event.view);
23410     }
23411
23412     nopropagation$1();
23413     interrupt(that);
23414     redraw.call(that);
23415     emit.start();
23416
23417     function moved() {
23418       var point1 = mouse(that);
23419       if (shifting && !lockX && !lockY) {
23420         if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
23421         else lockX = true;
23422       }
23423       point = point1;
23424       moving = true;
23425       noevent$1();
23426       move();
23427     }
23428
23429     function move() {
23430       var t;
23431
23432       dx = point[0] - point0[0];
23433       dy = point[1] - point0[1];
23434
23435       switch (mode) {
23436         case MODE_SPACE:
23437         case MODE_DRAG: {
23438           if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
23439           if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
23440           break;
23441         }
23442         case MODE_HANDLE: {
23443           if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
23444           else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
23445           if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
23446           else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
23447           break;
23448         }
23449         case MODE_CENTER: {
23450           if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
23451           if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
23452           break;
23453         }
23454       }
23455
23456       if (e1 < w1) {
23457         signX *= -1;
23458         t = w0, w0 = e0, e0 = t;
23459         t = w1, w1 = e1, e1 = t;
23460         if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
23461       }
23462
23463       if (s1 < n1) {
23464         signY *= -1;
23465         t = n0, n0 = s0, s0 = t;
23466         t = n1, n1 = s1, s1 = t;
23467         if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
23468       }
23469
23470       if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
23471       if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
23472       if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
23473
23474       if (selection$$1[0][0] !== w1
23475           || selection$$1[0][1] !== n1
23476           || selection$$1[1][0] !== e1
23477           || selection$$1[1][1] !== s1) {
23478         state.selection = [[w1, n1], [e1, s1]];
23479         redraw.call(that);
23480         emit.brush();
23481       }
23482     }
23483
23484     function ended() {
23485       nopropagation$1();
23486       if (event.touches) {
23487         if (event.touches.length) return;
23488         if (touchending) clearTimeout(touchending);
23489         touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
23490         group.on("touchmove.brush touchend.brush touchcancel.brush", null);
23491       } else {
23492         yesdrag(event.view, moving);
23493         view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
23494       }
23495       group.attr("pointer-events", "all");
23496       overlay.attr("cursor", cursors.overlay);
23497       if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
23498       if (empty(selection$$1)) state.selection = null, redraw.call(that);
23499       emit.end();
23500     }
23501
23502     function keydowned() {
23503       switch (event.keyCode) {
23504         case 16: { // SHIFT
23505           shifting = signX && signY;
23506           break;
23507         }
23508         case 18: { // ALT
23509           if (mode === MODE_HANDLE) {
23510             if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23511             if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23512             mode = MODE_CENTER;
23513             move();
23514           }
23515           break;
23516         }
23517         case 32: { // SPACE; takes priority over ALT
23518           if (mode === MODE_HANDLE || mode === MODE_CENTER) {
23519             if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
23520             if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
23521             mode = MODE_SPACE;
23522             overlay.attr("cursor", cursors.selection);
23523             move();
23524           }
23525           break;
23526         }
23527         default: return;
23528       }
23529       noevent$1();
23530     }
23531
23532     function keyupped() {
23533       switch (event.keyCode) {
23534         case 16: { // SHIFT
23535           if (shifting) {
23536             lockX = lockY = shifting = false;
23537             move();
23538           }
23539           break;
23540         }
23541         case 18: { // ALT
23542           if (mode === MODE_CENTER) {
23543             if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23544             if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23545             mode = MODE_HANDLE;
23546             move();
23547           }
23548           break;
23549         }
23550         case 32: { // SPACE
23551           if (mode === MODE_SPACE) {
23552             if (event.altKey) {
23553               if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
23554               if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
23555               mode = MODE_CENTER;
23556             } else {
23557               if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
23558               if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
23559               mode = MODE_HANDLE;
23560             }
23561             overlay.attr("cursor", cursors[type]);
23562             move();
23563           }
23564           break;
23565         }
23566         default: return;
23567       }
23568       noevent$1();
23569     }
23570   }
23571
23572   function initialize() {
23573     var state = this.__brush || {selection: null};
23574     state.extent = extent.apply(this, arguments);
23575     state.dim = dim;
23576     return state;
23577   }
23578
23579   brush.extent = function(_) {
23580     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
23581   };
23582
23583   brush.filter = function(_) {
23584     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter;
23585   };
23586
23587   brush.handleSize = function(_) {
23588     return arguments.length ? (handleSize = +_, brush) : handleSize;
23589   };
23590
23591   brush.on = function() {
23592     var value = listeners.on.apply(listeners, arguments);
23593     return value === listeners ? brush : value;
23594   };
23595
23596   return brush;
23597 }
23598
23599 var cos = Math.cos;
23600 var sin = Math.sin;
23601 var pi$1 = Math.PI;
23602 var halfPi$1 = pi$1 / 2;
23603 var tau$1 = pi$1 * 2;
23604 var max$1 = Math.max;
23605
23606 function compareValue(compare) {
23607   return function(a, b) {
23608     return compare(
23609       a.source.value + a.target.value,
23610       b.source.value + b.target.value
23611     );
23612   };
23613 }
23614
23615 var chord = function() {
23616   var padAngle = 0,
23617       sortGroups = null,
23618       sortSubgroups = null,
23619       sortChords = null;
23620
23621   function chord(matrix) {
23622     var n = matrix.length,
23623         groupSums = [],
23624         groupIndex = sequence(n),
23625         subgroupIndex = [],
23626         chords = [],
23627         groups = chords.groups = new Array(n),
23628         subgroups = new Array(n * n),
23629         k,
23630         x,
23631         x0,
23632         dx,
23633         i,
23634         j;
23635
23636     // Compute the sum.
23637     k = 0, i = -1; while (++i < n) {
23638       x = 0, j = -1; while (++j < n) {
23639         x += matrix[i][j];
23640       }
23641       groupSums.push(x);
23642       subgroupIndex.push(sequence(n));
23643       k += x;
23644     }
23645
23646     // Sort groups…
23647     if (sortGroups) groupIndex.sort(function(a, b) {
23648       return sortGroups(groupSums[a], groupSums[b]);
23649     });
23650
23651     // Sort subgroups…
23652     if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
23653       d.sort(function(a, b) {
23654         return sortSubgroups(matrix[i][a], matrix[i][b]);
23655       });
23656     });
23657
23658     // Convert the sum to scaling factor for [0, 2pi].
23659     // TODO Allow start and end angle to be specified?
23660     // TODO Allow padding to be specified as percentage?
23661     k = max$1(0, tau$1 - padAngle * n) / k;
23662     dx = k ? padAngle : tau$1 / n;
23663
23664     // Compute the start and end angle for each group and subgroup.
23665     // Note: Opera has a bug reordering object literal properties!
23666     x = 0, i = -1; while (++i < n) {
23667       x0 = x, j = -1; while (++j < n) {
23668         var di = groupIndex[i],
23669             dj = subgroupIndex[di][j],
23670             v = matrix[di][dj],
23671             a0 = x,
23672             a1 = x += v * k;
23673         subgroups[dj * n + di] = {
23674           index: di,
23675           subindex: dj,
23676           startAngle: a0,
23677           endAngle: a1,
23678           value: v
23679         };
23680       }
23681       groups[di] = {
23682         index: di,
23683         startAngle: x0,
23684         endAngle: x,
23685         value: groupSums[di]
23686       };
23687       x += dx;
23688     }
23689
23690     // Generate chords for each (non-empty) subgroup-subgroup link.
23691     i = -1; while (++i < n) {
23692       j = i - 1; while (++j < n) {
23693         var source = subgroups[j * n + i],
23694             target = subgroups[i * n + j];
23695         if (source.value || target.value) {
23696           chords.push(source.value < target.value
23697               ? {source: target, target: source}
23698               : {source: source, target: target});
23699         }
23700       }
23701     }
23702
23703     return sortChords ? chords.sort(sortChords) : chords;
23704   }
23705
23706   chord.padAngle = function(_) {
23707     return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
23708   };
23709
23710   chord.sortGroups = function(_) {
23711     return arguments.length ? (sortGroups = _, chord) : sortGroups;
23712   };
23713
23714   chord.sortSubgroups = function(_) {
23715     return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
23716   };
23717
23718   chord.sortChords = function(_) {
23719     return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
23720   };
23721
23722   return chord;
23723 };
23724
23725 var slice$2 = Array.prototype.slice;
23726
23727 var constant$5 = function(x) {
23728   return function() {
23729     return x;
23730   };
23731 };
23732
23733 var pi$2 = Math.PI;
23734 var tau$2 = 2 * pi$2;
23735 var epsilon$1 = 1e-6;
23736 var tauEpsilon = tau$2 - epsilon$1;
23737
23738 function Path() {
23739   this._x0 = this._y0 = // start of current subpath
23740   this._x1 = this._y1 = null; // end of current subpath
23741   this._ = "";
23742 }
23743
23744 function path() {
23745   return new Path;
23746 }
23747
23748 Path.prototype = path.prototype = {
23749   constructor: Path,
23750   moveTo: function(x, y) {
23751     this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
23752   },
23753   closePath: function() {
23754     if (this._x1 !== null) {
23755       this._x1 = this._x0, this._y1 = this._y0;
23756       this._ += "Z";
23757     }
23758   },
23759   lineTo: function(x, y) {
23760     this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
23761   },
23762   quadraticCurveTo: function(x1, y1, x, y) {
23763     this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
23764   },
23765   bezierCurveTo: function(x1, y1, x2, y2, x, y) {
23766     this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
23767   },
23768   arcTo: function(x1, y1, x2, y2, r) {
23769     x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
23770     var x0 = this._x1,
23771         y0 = this._y1,
23772         x21 = x2 - x1,
23773         y21 = y2 - y1,
23774         x01 = x0 - x1,
23775         y01 = y0 - y1,
23776         l01_2 = x01 * x01 + y01 * y01;
23777
23778     // Is the radius negative? Error.
23779     if (r < 0) throw new Error("negative radius: " + r);
23780
23781     // Is this path empty? Move to (x1,y1).
23782     if (this._x1 === null) {
23783       this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
23784     }
23785
23786     // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
23787     else if (!(l01_2 > epsilon$1)) {}
23788
23789     // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
23790     // Equivalently, is (x1,y1) coincident with (x2,y2)?
23791     // Or, is the radius zero? Line to (x1,y1).
23792     else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) {
23793       this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
23794     }
23795
23796     // Otherwise, draw an arc!
23797     else {
23798       var x20 = x2 - x0,
23799           y20 = y2 - y0,
23800           l21_2 = x21 * x21 + y21 * y21,
23801           l20_2 = x20 * x20 + y20 * y20,
23802           l21 = Math.sqrt(l21_2),
23803           l01 = Math.sqrt(l01_2),
23804           l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
23805           t01 = l / l01,
23806           t21 = l / l21;
23807
23808       // If the start tangent is not coincident with (x0,y0), line to.
23809       if (Math.abs(t01 - 1) > epsilon$1) {
23810         this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
23811       }
23812
23813       this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
23814     }
23815   },
23816   arc: function(x, y, r, a0, a1, ccw) {
23817     x = +x, y = +y, r = +r;
23818     var dx = r * Math.cos(a0),
23819         dy = r * Math.sin(a0),
23820         x0 = x + dx,
23821         y0 = y + dy,
23822         cw = 1 ^ ccw,
23823         da = ccw ? a0 - a1 : a1 - a0;
23824
23825     // Is the radius negative? Error.
23826     if (r < 0) throw new Error("negative radius: " + r);
23827
23828     // Is this path empty? Move to (x0,y0).
23829     if (this._x1 === null) {
23830       this._ += "M" + x0 + "," + y0;
23831     }
23832
23833     // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
23834     else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) {
23835       this._ += "L" + x0 + "," + y0;
23836     }
23837
23838     // Is this arc empty? We’re done.
23839     if (!r) return;
23840
23841     // Is this a complete circle? Draw two arcs to complete the circle.
23842     if (da > tauEpsilon) {
23843       this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
23844     }
23845
23846     // Otherwise, draw an arc!
23847     else {
23848       if (da < 0) da = da % tau$2 + tau$2;
23849       this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
23850     }
23851   },
23852   rect: function(x, y, w, h) {
23853     this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
23854   },
23855   toString: function() {
23856     return this._;
23857   }
23858 };
23859
23860 function defaultSource(d) {
23861   return d.source;
23862 }
23863
23864 function defaultTarget(d) {
23865   return d.target;
23866 }
23867
23868 function defaultRadius(d) {
23869   return d.radius;
23870 }
23871
23872 function defaultStartAngle(d) {
23873   return d.startAngle;
23874 }
23875
23876 function defaultEndAngle(d) {
23877   return d.endAngle;
23878 }
23879
23880 var ribbon = function() {
23881   var source = defaultSource,
23882       target = defaultTarget,
23883       radius = defaultRadius,
23884       startAngle = defaultStartAngle,
23885       endAngle = defaultEndAngle,
23886       context = null;
23887
23888   function ribbon() {
23889     var buffer,
23890         argv = slice$2.call(arguments),
23891         s = source.apply(this, argv),
23892         t = target.apply(this, argv),
23893         sr = +radius.apply(this, (argv[0] = s, argv)),
23894         sa0 = startAngle.apply(this, argv) - halfPi$1,
23895         sa1 = endAngle.apply(this, argv) - halfPi$1,
23896         sx0 = sr * cos(sa0),
23897         sy0 = sr * sin(sa0),
23898         tr = +radius.apply(this, (argv[0] = t, argv)),
23899         ta0 = startAngle.apply(this, argv) - halfPi$1,
23900         ta1 = endAngle.apply(this, argv) - halfPi$1;
23901
23902     if (!context) context = buffer = path();
23903
23904     context.moveTo(sx0, sy0);
23905     context.arc(0, 0, sr, sa0, sa1);
23906     if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
23907       context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
23908       context.arc(0, 0, tr, ta0, ta1);
23909     }
23910     context.quadraticCurveTo(0, 0, sx0, sy0);
23911     context.closePath();
23912
23913     if (buffer) return context = null, buffer + "" || null;
23914   }
23915
23916   ribbon.radius = function(_) {
23917     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius;
23918   };
23919
23920   ribbon.startAngle = function(_) {
23921     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle;
23922   };
23923
23924   ribbon.endAngle = function(_) {
23925     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle;
23926   };
23927
23928   ribbon.source = function(_) {
23929     return arguments.length ? (source = _, ribbon) : source;
23930   };
23931
23932   ribbon.target = function(_) {
23933     return arguments.length ? (target = _, ribbon) : target;
23934   };
23935
23936   ribbon.context = function(_) {
23937     return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
23938   };
23939
23940   return ribbon;
23941 };
23942
23943 var prefix = "$";
23944
23945 function Map() {}
23946
23947 Map.prototype = map$1.prototype = {
23948   constructor: Map,
23949   has: function(key) {
23950     return (prefix + key) in this;
23951   },
23952   get: function(key) {
23953     return this[prefix + key];
23954   },
23955   set: function(key, value) {
23956     this[prefix + key] = value;
23957     return this;
23958   },
23959   remove: function(key) {
23960     var property = prefix + key;
23961     return property in this && delete this[property];
23962   },
23963   clear: function() {
23964     for (var property in this) if (property[0] === prefix) delete this[property];
23965   },
23966   keys: function() {
23967     var keys = [];
23968     for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
23969     return keys;
23970   },
23971   values: function() {
23972     var values = [];
23973     for (var property in this) if (property[0] === prefix) values.push(this[property]);
23974     return values;
23975   },
23976   entries: function() {
23977     var entries = [];
23978     for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
23979     return entries;
23980   },
23981   size: function() {
23982     var size = 0;
23983     for (var property in this) if (property[0] === prefix) ++size;
23984     return size;
23985   },
23986   empty: function() {
23987     for (var property in this) if (property[0] === prefix) return false;
23988     return true;
23989   },
23990   each: function(f) {
23991     for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
23992   }
23993 };
23994
23995 function map$1(object, f) {
23996   var map = new Map;
23997
23998   // Copy constructor.
23999   if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
24000
24001   // Index array by numeric index or specified key function.
24002   else if (Array.isArray(object)) {
24003     var i = -1,
24004         n = object.length,
24005         o;
24006
24007     if (f == null) while (++i < n) map.set(i, object[i]);
24008     else while (++i < n) map.set(f(o = object[i], i, object), o);
24009   }
24010
24011   // Convert object to map.
24012   else if (object) for (var key in object) map.set(key, object[key]);
24013
24014   return map;
24015 }
24016
24017 var nest = function() {
24018   var keys = [],
24019       sortKeys = [],
24020       sortValues,
24021       rollup,
24022       nest;
24023
24024   function apply(array, depth, createResult, setResult) {
24025     if (depth >= keys.length) return rollup != null
24026         ? rollup(array) : (sortValues != null
24027         ? array.sort(sortValues)
24028         : array);
24029
24030     var i = -1,
24031         n = array.length,
24032         key = keys[depth++],
24033         keyValue,
24034         value,
24035         valuesByKey = map$1(),
24036         values,
24037         result = createResult();
24038
24039     while (++i < n) {
24040       if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
24041         values.push(value);
24042       } else {
24043         valuesByKey.set(keyValue, [value]);
24044       }
24045     }
24046
24047     valuesByKey.each(function(values, key) {
24048       setResult(result, key, apply(values, depth, createResult, setResult));
24049     });
24050
24051     return result;
24052   }
24053
24054   function entries(map, depth) {
24055     if (++depth > keys.length) return map;
24056     var array, sortKey = sortKeys[depth - 1];
24057     if (rollup != null && depth >= keys.length) array = map.entries();
24058     else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
24059     return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
24060   }
24061
24062   return nest = {
24063     object: function(array) { return apply(array, 0, createObject, setObject); },
24064     map: function(array) { return apply(array, 0, createMap, setMap); },
24065     entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
24066     key: function(d) { keys.push(d); return nest; },
24067     sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
24068     sortValues: function(order) { sortValues = order; return nest; },
24069     rollup: function(f) { rollup = f; return nest; }
24070   };
24071 };
24072
24073 function createObject() {
24074   return {};
24075 }
24076
24077 function setObject(object, key, value) {
24078   object[key] = value;
24079 }
24080
24081 function createMap() {
24082   return map$1();
24083 }
24084
24085 function setMap(map, key, value) {
24086   map.set(key, value);
24087 }
24088
24089 function Set() {}
24090
24091 var proto = map$1.prototype;
24092
24093 Set.prototype = set$2.prototype = {
24094   constructor: Set,
24095   has: proto.has,
24096   add: function(value) {
24097     value += "";
24098     this[prefix + value] = value;
24099     return this;
24100   },
24101   remove: proto.remove,
24102   clear: proto.clear,
24103   values: proto.keys,
24104   size: proto.size,
24105   empty: proto.empty,
24106   each: proto.each
24107 };
24108
24109 function set$2(object, f) {
24110   var set = new Set;
24111
24112   // Copy constructor.
24113   if (object instanceof Set) object.each(function(value) { set.add(value); });
24114
24115   // Otherwise, assume it’s an array.
24116   else if (object) {
24117     var i = -1, n = object.length;
24118     if (f == null) while (++i < n) set.add(object[i]);
24119     else while (++i < n) set.add(f(object[i], i, object));
24120   }
24121
24122   return set;
24123 }
24124
24125 var keys = function(map) {
24126   var keys = [];
24127   for (var key in map) keys.push(key);
24128   return keys;
24129 };
24130
24131 var values = function(map) {
24132   var values = [];
24133   for (var key in map) values.push(map[key]);
24134   return values;
24135 };
24136
24137 var entries = function(map) {
24138   var entries = [];
24139   for (var key in map) entries.push({key: key, value: map[key]});
24140   return entries;
24141 };
24142
24143 function objectConverter(columns) {
24144   return new Function("d", "return {" + columns.map(function(name, i) {
24145     return JSON.stringify(name) + ": d[" + i + "]";
24146   }).join(",") + "}");
24147 }
24148
24149 function customConverter(columns, f) {
24150   var object = objectConverter(columns);
24151   return function(row, i) {
24152     return f(object(row), i, columns);
24153   };
24154 }
24155
24156 // Compute unique columns in order of discovery.
24157 function inferColumns(rows) {
24158   var columnSet = Object.create(null),
24159       columns = [];
24160
24161   rows.forEach(function(row) {
24162     for (var column in row) {
24163       if (!(column in columnSet)) {
24164         columns.push(columnSet[column] = column);
24165       }
24166     }
24167   });
24168
24169   return columns;
24170 }
24171
24172 var dsv = function(delimiter) {
24173   var reFormat = new RegExp("[\"" + delimiter + "\n]"),
24174       delimiterCode = delimiter.charCodeAt(0);
24175
24176   function parse(text, f) {
24177     var convert, columns, rows = parseRows(text, function(row, i) {
24178       if (convert) return convert(row, i - 1);
24179       columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
24180     });
24181     rows.columns = columns;
24182     return rows;
24183   }
24184
24185   function parseRows(text, f) {
24186     var EOL = {}, // sentinel value for end-of-line
24187         EOF = {}, // sentinel value for end-of-file
24188         rows = [], // output rows
24189         N = text.length,
24190         I = 0, // current character index
24191         n = 0, // the current line number
24192         t, // the current token
24193         eol; // is the current token followed by EOL?
24194
24195     function token() {
24196       if (I >= N) return EOF; // special case: end of file
24197       if (eol) return eol = false, EOL; // special case: end of line
24198
24199       // special case: quotes
24200       var j = I, c;
24201       if (text.charCodeAt(j) === 34) {
24202         var i = j;
24203         while (i++ < N) {
24204           if (text.charCodeAt(i) === 34) {
24205             if (text.charCodeAt(i + 1) !== 34) break;
24206             ++i;
24207           }
24208         }
24209         I = i + 2;
24210         c = text.charCodeAt(i + 1);
24211         if (c === 13) {
24212           eol = true;
24213           if (text.charCodeAt(i + 2) === 10) ++I;
24214         } else if (c === 10) {
24215           eol = true;
24216         }
24217         return text.slice(j + 1, i).replace(/""/g, "\"");
24218       }
24219
24220       // common case: find next delimiter or newline
24221       while (I < N) {
24222         var k = 1;
24223         c = text.charCodeAt(I++);
24224         if (c === 10) eol = true; // \n
24225         else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
24226         else if (c !== delimiterCode) continue;
24227         return text.slice(j, I - k);
24228       }
24229
24230       // special case: last token before EOF
24231       return text.slice(j);
24232     }
24233
24234     while ((t = token()) !== EOF) {
24235       var a = [];
24236       while (t !== EOL && t !== EOF) {
24237         a.push(t);
24238         t = token();
24239       }
24240       if (f && (a = f(a, n++)) == null) continue;
24241       rows.push(a);
24242     }
24243
24244     return rows;
24245   }
24246
24247   function format(rows, columns) {
24248     if (columns == null) columns = inferColumns(rows);
24249     return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
24250       return columns.map(function(column) {
24251         return formatValue(row[column]);
24252       }).join(delimiter);
24253     })).join("\n");
24254   }
24255
24256   function formatRows(rows) {
24257     return rows.map(formatRow).join("\n");
24258   }
24259
24260   function formatRow(row) {
24261     return row.map(formatValue).join(delimiter);
24262   }
24263
24264   function formatValue(text) {
24265     return text == null ? ""
24266         : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
24267         : text;
24268   }
24269
24270   return {
24271     parse: parse,
24272     parseRows: parseRows,
24273     format: format,
24274     formatRows: formatRows
24275   };
24276 };
24277
24278 var csv = dsv(",");
24279
24280 var csvParse = csv.parse;
24281 var csvParseRows = csv.parseRows;
24282 var csvFormat = csv.format;
24283 var csvFormatRows = csv.formatRows;
24284
24285 var tsv = dsv("\t");
24286
24287 var tsvParse = tsv.parse;
24288 var tsvParseRows = tsv.parseRows;
24289 var tsvFormat = tsv.format;
24290 var tsvFormatRows = tsv.formatRows;
24291
24292 var center$1 = function(x, y) {
24293   var nodes;
24294
24295   if (x == null) x = 0;
24296   if (y == null) y = 0;
24297
24298   function force() {
24299     var i,
24300         n = nodes.length,
24301         node,
24302         sx = 0,
24303         sy = 0;
24304
24305     for (i = 0; i < n; ++i) {
24306       node = nodes[i], sx += node.x, sy += node.y;
24307     }
24308
24309     for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
24310       node = nodes[i], node.x -= sx, node.y -= sy;
24311     }
24312   }
24313
24314   force.initialize = function(_) {
24315     nodes = _;
24316   };
24317
24318   force.x = function(_) {
24319     return arguments.length ? (x = +_, force) : x;
24320   };
24321
24322   force.y = function(_) {
24323     return arguments.length ? (y = +_, force) : y;
24324   };
24325
24326   return force;
24327 };
24328
24329 var constant$6 = function(x) {
24330   return function() {
24331     return x;
24332   };
24333 };
24334
24335 var jiggle = function() {
24336   return (Math.random() - 0.5) * 1e-6;
24337 };
24338
24339 var tree_add = function(d) {
24340   var x = +this._x.call(null, d),
24341       y = +this._y.call(null, d);
24342   return add(this.cover(x, y), x, y, d);
24343 };
24344
24345 function add(tree, x, y, d) {
24346   if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
24347
24348   var parent,
24349       node = tree._root,
24350       leaf = {data: d},
24351       x0 = tree._x0,
24352       y0 = tree._y0,
24353       x1 = tree._x1,
24354       y1 = tree._y1,
24355       xm,
24356       ym,
24357       xp,
24358       yp,
24359       right,
24360       bottom,
24361       i,
24362       j;
24363
24364   // If the tree is empty, initialize the root as a leaf.
24365   if (!node) return tree._root = leaf, tree;
24366
24367   // Find the existing leaf for the new point, or add it.
24368   while (node.length) {
24369     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24370     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24371     if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
24372   }
24373
24374   // Is the new point is exactly coincident with the existing point?
24375   xp = +tree._x.call(null, node.data);
24376   yp = +tree._y.call(null, node.data);
24377   if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
24378
24379   // Otherwise, split the leaf node until the old and new point are separated.
24380   do {
24381     parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
24382     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24383     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24384   } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
24385   return parent[j] = node, parent[i] = leaf, tree;
24386 }
24387
24388 function addAll(data) {
24389   var d, i, n = data.length,
24390       x,
24391       y,
24392       xz = new Array(n),
24393       yz = new Array(n),
24394       x0 = Infinity,
24395       y0 = Infinity,
24396       x1 = -Infinity,
24397       y1 = -Infinity;
24398
24399   // Compute the points and their extent.
24400   for (i = 0; i < n; ++i) {
24401     if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
24402     xz[i] = x;
24403     yz[i] = y;
24404     if (x < x0) x0 = x;
24405     if (x > x1) x1 = x;
24406     if (y < y0) y0 = y;
24407     if (y > y1) y1 = y;
24408   }
24409
24410   // If there were no (valid) points, inherit the existing extent.
24411   if (x1 < x0) x0 = this._x0, x1 = this._x1;
24412   if (y1 < y0) y0 = this._y0, y1 = this._y1;
24413
24414   // Expand the tree to cover the new points.
24415   this.cover(x0, y0).cover(x1, y1);
24416
24417   // Add the new points.
24418   for (i = 0; i < n; ++i) {
24419     add(this, xz[i], yz[i], data[i]);
24420   }
24421
24422   return this;
24423 }
24424
24425 var tree_cover = function(x, y) {
24426   if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
24427
24428   var x0 = this._x0,
24429       y0 = this._y0,
24430       x1 = this._x1,
24431       y1 = this._y1;
24432
24433   // If the quadtree has no extent, initialize them.
24434   // Integer extent are necessary so that if we later double the extent,
24435   // the existing quadrant boundaries don’t change due to floating point error!
24436   if (isNaN(x0)) {
24437     x1 = (x0 = Math.floor(x)) + 1;
24438     y1 = (y0 = Math.floor(y)) + 1;
24439   }
24440
24441   // Otherwise, double repeatedly to cover.
24442   else if (x0 > x || x > x1 || y0 > y || y > y1) {
24443     var z = x1 - x0,
24444         node = this._root,
24445         parent,
24446         i;
24447
24448     switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
24449       case 0: {
24450         do parent = new Array(4), parent[i] = node, node = parent;
24451         while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
24452         break;
24453       }
24454       case 1: {
24455         do parent = new Array(4), parent[i] = node, node = parent;
24456         while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
24457         break;
24458       }
24459       case 2: {
24460         do parent = new Array(4), parent[i] = node, node = parent;
24461         while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
24462         break;
24463       }
24464       case 3: {
24465         do parent = new Array(4), parent[i] = node, node = parent;
24466         while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
24467         break;
24468       }
24469     }
24470
24471     if (this._root && this._root.length) this._root = node;
24472   }
24473
24474   // If the quadtree covers the point already, just return.
24475   else return this;
24476
24477   this._x0 = x0;
24478   this._y0 = y0;
24479   this._x1 = x1;
24480   this._y1 = y1;
24481   return this;
24482 };
24483
24484 var tree_data = function() {
24485   var data = [];
24486   this.visit(function(node) {
24487     if (!node.length) do data.push(node.data); while (node = node.next)
24488   });
24489   return data;
24490 };
24491
24492 var tree_extent = function(_) {
24493   return arguments.length
24494       ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
24495       : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
24496 };
24497
24498 var Quad = function(node, x0, y0, x1, y1) {
24499   this.node = node;
24500   this.x0 = x0;
24501   this.y0 = y0;
24502   this.x1 = x1;
24503   this.y1 = y1;
24504 };
24505
24506 var tree_find = function(x, y, radius) {
24507   var data,
24508       x0 = this._x0,
24509       y0 = this._y0,
24510       x1,
24511       y1,
24512       x2,
24513       y2,
24514       x3 = this._x1,
24515       y3 = this._y1,
24516       quads = [],
24517       node = this._root,
24518       q,
24519       i;
24520
24521   if (node) quads.push(new Quad(node, x0, y0, x3, y3));
24522   if (radius == null) radius = Infinity;
24523   else {
24524     x0 = x - radius, y0 = y - radius;
24525     x3 = x + radius, y3 = y + radius;
24526     radius *= radius;
24527   }
24528
24529   while (q = quads.pop()) {
24530
24531     // Stop searching if this quadrant can’t contain a closer node.
24532     if (!(node = q.node)
24533         || (x1 = q.x0) > x3
24534         || (y1 = q.y0) > y3
24535         || (x2 = q.x1) < x0
24536         || (y2 = q.y1) < y0) continue;
24537
24538     // Bisect the current quadrant.
24539     if (node.length) {
24540       var xm = (x1 + x2) / 2,
24541           ym = (y1 + y2) / 2;
24542
24543       quads.push(
24544         new Quad(node[3], xm, ym, x2, y2),
24545         new Quad(node[2], x1, ym, xm, y2),
24546         new Quad(node[1], xm, y1, x2, ym),
24547         new Quad(node[0], x1, y1, xm, ym)
24548       );
24549
24550       // Visit the closest quadrant first.
24551       if (i = (y >= ym) << 1 | (x >= xm)) {
24552         q = quads[quads.length - 1];
24553         quads[quads.length - 1] = quads[quads.length - 1 - i];
24554         quads[quads.length - 1 - i] = q;
24555       }
24556     }
24557
24558     // Visit this point. (Visiting coincident points isn’t necessary!)
24559     else {
24560       var dx = x - +this._x.call(null, node.data),
24561           dy = y - +this._y.call(null, node.data),
24562           d2 = dx * dx + dy * dy;
24563       if (d2 < radius) {
24564         var d = Math.sqrt(radius = d2);
24565         x0 = x - d, y0 = y - d;
24566         x3 = x + d, y3 = y + d;
24567         data = node.data;
24568       }
24569     }
24570   }
24571
24572   return data;
24573 };
24574
24575 var tree_remove = function(d) {
24576   if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
24577
24578   var parent,
24579       node = this._root,
24580       retainer,
24581       previous,
24582       next,
24583       x0 = this._x0,
24584       y0 = this._y0,
24585       x1 = this._x1,
24586       y1 = this._y1,
24587       x,
24588       y,
24589       xm,
24590       ym,
24591       right,
24592       bottom,
24593       i,
24594       j;
24595
24596   // If the tree is empty, initialize the root as a leaf.
24597   if (!node) return this;
24598
24599   // Find the leaf node for the point.
24600   // While descending, also retain the deepest parent with a non-removed sibling.
24601   if (node.length) while (true) {
24602     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
24603     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
24604     if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
24605     if (!node.length) break;
24606     if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
24607   }
24608
24609   // Find the point to remove.
24610   while (node.data !== d) if (!(previous = node, node = node.next)) return this;
24611   if (next = node.next) delete node.next;
24612
24613   // If there are multiple coincident points, remove just the point.
24614   if (previous) return (next ? previous.next = next : delete previous.next), this;
24615
24616   // If this is the root point, remove it.
24617   if (!parent) return this._root = next, this;
24618
24619   // Remove this leaf.
24620   next ? parent[i] = next : delete parent[i];
24621
24622   // If the parent now contains exactly one leaf, collapse superfluous parents.
24623   if ((node = parent[0] || parent[1] || parent[2] || parent[3])
24624       && node === (parent[3] || parent[2] || parent[1] || parent[0])
24625       && !node.length) {
24626     if (retainer) retainer[j] = node;
24627     else this._root = node;
24628   }
24629
24630   return this;
24631 };
24632
24633 function removeAll(data) {
24634   for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
24635   return this;
24636 }
24637
24638 var tree_root = function() {
24639   return this._root;
24640 };
24641
24642 var tree_size = function() {
24643   var size = 0;
24644   this.visit(function(node) {
24645     if (!node.length) do ++size; while (node = node.next)
24646   });
24647   return size;
24648 };
24649
24650 var tree_visit = function(callback) {
24651   var quads = [], q, node = this._root, child, x0, y0, x1, y1;
24652   if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
24653   while (q = quads.pop()) {
24654     if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
24655       var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24656       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24657       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24658       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24659       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24660     }
24661   }
24662   return this;
24663 };
24664
24665 var tree_visitAfter = function(callback) {
24666   var quads = [], next = [], q;
24667   if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
24668   while (q = quads.pop()) {
24669     var node = q.node;
24670     if (node.length) {
24671       var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
24672       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
24673       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
24674       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
24675       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
24676     }
24677     next.push(q);
24678   }
24679   while (q = next.pop()) {
24680     callback(q.node, q.x0, q.y0, q.x1, q.y1);
24681   }
24682   return this;
24683 };
24684
24685 function defaultX(d) {
24686   return d[0];
24687 }
24688
24689 var tree_x = function(_) {
24690   return arguments.length ? (this._x = _, this) : this._x;
24691 };
24692
24693 function defaultY(d) {
24694   return d[1];
24695 }
24696
24697 var tree_y = function(_) {
24698   return arguments.length ? (this._y = _, this) : this._y;
24699 };
24700
24701 function quadtree(nodes, x, y) {
24702   var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
24703   return nodes == null ? tree : tree.addAll(nodes);
24704 }
24705
24706 function Quadtree(x, y, x0, y0, x1, y1) {
24707   this._x = x;
24708   this._y = y;
24709   this._x0 = x0;
24710   this._y0 = y0;
24711   this._x1 = x1;
24712   this._y1 = y1;
24713   this._root = undefined;
24714 }
24715
24716 function leaf_copy(leaf) {
24717   var copy = {data: leaf.data}, next = copy;
24718   while (leaf = leaf.next) next = next.next = {data: leaf.data};
24719   return copy;
24720 }
24721
24722 var treeProto = quadtree.prototype = Quadtree.prototype;
24723
24724 treeProto.copy = function() {
24725   var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
24726       node = this._root,
24727       nodes,
24728       child;
24729
24730   if (!node) return copy;
24731
24732   if (!node.length) return copy._root = leaf_copy(node), copy;
24733
24734   nodes = [{source: node, target: copy._root = new Array(4)}];
24735   while (node = nodes.pop()) {
24736     for (var i = 0; i < 4; ++i) {
24737       if (child = node.source[i]) {
24738         if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
24739         else node.target[i] = leaf_copy(child);
24740       }
24741     }
24742   }
24743
24744   return copy;
24745 };
24746
24747 treeProto.add = tree_add;
24748 treeProto.addAll = addAll;
24749 treeProto.cover = tree_cover;
24750 treeProto.data = tree_data;
24751 treeProto.extent = tree_extent;
24752 treeProto.find = tree_find;
24753 treeProto.remove = tree_remove;
24754 treeProto.removeAll = removeAll;
24755 treeProto.root = tree_root;
24756 treeProto.size = tree_size;
24757 treeProto.visit = tree_visit;
24758 treeProto.visitAfter = tree_visitAfter;
24759 treeProto.x = tree_x;
24760 treeProto.y = tree_y;
24761
24762 function x(d) {
24763   return d.x + d.vx;
24764 }
24765
24766 function y(d) {
24767   return d.y + d.vy;
24768 }
24769
24770 var collide = function(radius) {
24771   var nodes,
24772       radii,
24773       strength = 1,
24774       iterations = 1;
24775
24776   if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius);
24777
24778   function force() {
24779     var i, n = nodes.length,
24780         tree,
24781         node,
24782         xi,
24783         yi,
24784         ri,
24785         ri2;
24786
24787     for (var k = 0; k < iterations; ++k) {
24788       tree = quadtree(nodes, x, y).visitAfter(prepare);
24789       for (i = 0; i < n; ++i) {
24790         node = nodes[i];
24791         ri = radii[node.index], ri2 = ri * ri;
24792         xi = node.x + node.vx;
24793         yi = node.y + node.vy;
24794         tree.visit(apply);
24795       }
24796     }
24797
24798     function apply(quad, x0, y0, x1, y1) {
24799       var data = quad.data, rj = quad.r, r = ri + rj;
24800       if (data) {
24801         if (data.index > node.index) {
24802           var x = xi - data.x - data.vx,
24803               y = yi - data.y - data.vy,
24804               l = x * x + y * y;
24805           if (l < r * r) {
24806             if (x === 0) x = jiggle(), l += x * x;
24807             if (y === 0) y = jiggle(), l += y * y;
24808             l = (r - (l = Math.sqrt(l))) / l * strength;
24809             node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
24810             node.vy += (y *= l) * r;
24811             data.vx -= x * (r = 1 - r);
24812             data.vy -= y * r;
24813           }
24814         }
24815         return;
24816       }
24817       return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
24818     }
24819   }
24820
24821   function prepare(quad) {
24822     if (quad.data) return quad.r = radii[quad.data.index];
24823     for (var i = quad.r = 0; i < 4; ++i) {
24824       if (quad[i] && quad[i].r > quad.r) {
24825         quad.r = quad[i].r;
24826       }
24827     }
24828   }
24829
24830   function initialize() {
24831     if (!nodes) return;
24832     var i, n = nodes.length, node;
24833     radii = new Array(n);
24834     for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
24835   }
24836
24837   force.initialize = function(_) {
24838     nodes = _;
24839     initialize();
24840   };
24841
24842   force.iterations = function(_) {
24843     return arguments.length ? (iterations = +_, force) : iterations;
24844   };
24845
24846   force.strength = function(_) {
24847     return arguments.length ? (strength = +_, force) : strength;
24848   };
24849
24850   force.radius = function(_) {
24851     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius;
24852   };
24853
24854   return force;
24855 };
24856
24857 function index$3(d) {
24858   return d.index;
24859 }
24860
24861 function find(nodeById, nodeId) {
24862   var node = nodeById.get(nodeId);
24863   if (!node) throw new Error("missing: " + nodeId);
24864   return node;
24865 }
24866
24867 var link = function(links) {
24868   var id = index$3,
24869       strength = defaultStrength,
24870       strengths,
24871       distance = constant$6(30),
24872       distances,
24873       nodes,
24874       count,
24875       bias,
24876       iterations = 1;
24877
24878   if (links == null) links = [];
24879
24880   function defaultStrength(link) {
24881     return 1 / Math.min(count[link.source.index], count[link.target.index]);
24882   }
24883
24884   function force(alpha) {
24885     for (var k = 0, n = links.length; k < iterations; ++k) {
24886       for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
24887         link = links[i], source = link.source, target = link.target;
24888         x = target.x + target.vx - source.x - source.vx || jiggle();
24889         y = target.y + target.vy - source.y - source.vy || jiggle();
24890         l = Math.sqrt(x * x + y * y);
24891         l = (l - distances[i]) / l * alpha * strengths[i];
24892         x *= l, y *= l;
24893         target.vx -= x * (b = bias[i]);
24894         target.vy -= y * b;
24895         source.vx += x * (b = 1 - b);
24896         source.vy += y * b;
24897       }
24898     }
24899   }
24900
24901   function initialize() {
24902     if (!nodes) return;
24903
24904     var i,
24905         n = nodes.length,
24906         m = links.length,
24907         nodeById = map$1(nodes, id),
24908         link;
24909
24910     for (i = 0, count = new Array(n); i < m; ++i) {
24911       link = links[i], link.index = i;
24912       if (typeof link.source !== "object") link.source = find(nodeById, link.source);
24913       if (typeof link.target !== "object") link.target = find(nodeById, link.target);
24914       count[link.source.index] = (count[link.source.index] || 0) + 1;
24915       count[link.target.index] = (count[link.target.index] || 0) + 1;
24916     }
24917
24918     for (i = 0, bias = new Array(m); i < m; ++i) {
24919       link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
24920     }
24921
24922     strengths = new Array(m), initializeStrength();
24923     distances = new Array(m), initializeDistance();
24924   }
24925
24926   function initializeStrength() {
24927     if (!nodes) return;
24928
24929     for (var i = 0, n = links.length; i < n; ++i) {
24930       strengths[i] = +strength(links[i], i, links);
24931     }
24932   }
24933
24934   function initializeDistance() {
24935     if (!nodes) return;
24936
24937     for (var i = 0, n = links.length; i < n; ++i) {
24938       distances[i] = +distance(links[i], i, links);
24939     }
24940   }
24941
24942   force.initialize = function(_) {
24943     nodes = _;
24944     initialize();
24945   };
24946
24947   force.links = function(_) {
24948     return arguments.length ? (links = _, initialize(), force) : links;
24949   };
24950
24951   force.id = function(_) {
24952     return arguments.length ? (id = _, force) : id;
24953   };
24954
24955   force.iterations = function(_) {
24956     return arguments.length ? (iterations = +_, force) : iterations;
24957   };
24958
24959   force.strength = function(_) {
24960     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength;
24961   };
24962
24963   force.distance = function(_) {
24964     return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance;
24965   };
24966
24967   return force;
24968 };
24969
24970 function x$1(d) {
24971   return d.x;
24972 }
24973
24974 function y$1(d) {
24975   return d.y;
24976 }
24977
24978 var initialRadius = 10;
24979 var initialAngle = Math.PI * (3 - Math.sqrt(5));
24980
24981 var simulation = function(nodes) {
24982   var simulation,
24983       alpha = 1,
24984       alphaMin = 0.001,
24985       alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
24986       alphaTarget = 0,
24987       velocityDecay = 0.6,
24988       forces = map$1(),
24989       stepper = timer(step),
24990       event = dispatch("tick", "end");
24991
24992   if (nodes == null) nodes = [];
24993
24994   function step() {
24995     tick();
24996     event.call("tick", simulation);
24997     if (alpha < alphaMin) {
24998       stepper.stop();
24999       event.call("end", simulation);
25000     }
25001   }
25002
25003   function tick() {
25004     var i, n = nodes.length, node;
25005
25006     alpha += (alphaTarget - alpha) * alphaDecay;
25007
25008     forces.each(function(force) {
25009       force(alpha);
25010     });
25011
25012     for (i = 0; i < n; ++i) {
25013       node = nodes[i];
25014       if (node.fx == null) node.x += node.vx *= velocityDecay;
25015       else node.x = node.fx, node.vx = 0;
25016       if (node.fy == null) node.y += node.vy *= velocityDecay;
25017       else node.y = node.fy, node.vy = 0;
25018     }
25019   }
25020
25021   function initializeNodes() {
25022     for (var i = 0, n = nodes.length, node; i < n; ++i) {
25023       node = nodes[i], node.index = i;
25024       if (isNaN(node.x) || isNaN(node.y)) {
25025         var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
25026         node.x = radius * Math.cos(angle);
25027         node.y = radius * Math.sin(angle);
25028       }
25029       if (isNaN(node.vx) || isNaN(node.vy)) {
25030         node.vx = node.vy = 0;
25031       }
25032     }
25033   }
25034
25035   function initializeForce(force) {
25036     if (force.initialize) force.initialize(nodes);
25037     return force;
25038   }
25039
25040   initializeNodes();
25041
25042   return simulation = {
25043     tick: tick,
25044
25045     restart: function() {
25046       return stepper.restart(step), simulation;
25047     },
25048
25049     stop: function() {
25050       return stepper.stop(), simulation;
25051     },
25052
25053     nodes: function(_) {
25054       return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
25055     },
25056
25057     alpha: function(_) {
25058       return arguments.length ? (alpha = +_, simulation) : alpha;
25059     },
25060
25061     alphaMin: function(_) {
25062       return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
25063     },
25064
25065     alphaDecay: function(_) {
25066       return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
25067     },
25068
25069     alphaTarget: function(_) {
25070       return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
25071     },
25072
25073     velocityDecay: function(_) {
25074       return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
25075     },
25076
25077     force: function(name, _) {
25078       return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
25079     },
25080
25081     find: function(x, y, radius) {
25082       var i = 0,
25083           n = nodes.length,
25084           dx,
25085           dy,
25086           d2,
25087           node,
25088           closest;
25089
25090       if (radius == null) radius = Infinity;
25091       else radius *= radius;
25092
25093       for (i = 0; i < n; ++i) {
25094         node = nodes[i];
25095         dx = x - node.x;
25096         dy = y - node.y;
25097         d2 = dx * dx + dy * dy;
25098         if (d2 < radius) closest = node, radius = d2;
25099       }
25100
25101       return closest;
25102     },
25103
25104     on: function(name, _) {
25105       return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
25106     }
25107   };
25108 };
25109
25110 var manyBody = function() {
25111   var nodes,
25112       node,
25113       alpha,
25114       strength = constant$6(-30),
25115       strengths,
25116       distanceMin2 = 1,
25117       distanceMax2 = Infinity,
25118       theta2 = 0.81;
25119
25120   function force(_) {
25121     var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate);
25122     for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
25123   }
25124
25125   function initialize() {
25126     if (!nodes) return;
25127     var i, n = nodes.length, node;
25128     strengths = new Array(n);
25129     for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
25130   }
25131
25132   function accumulate(quad) {
25133     var strength = 0, q, c, x$$1, y$$1, i;
25134
25135     // For internal nodes, accumulate forces from child quadrants.
25136     if (quad.length) {
25137       for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
25138         if ((q = quad[i]) && (c = q.value)) {
25139           strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
25140         }
25141       }
25142       quad.x = x$$1 / strength;
25143       quad.y = y$$1 / strength;
25144     }
25145
25146     // For leaf nodes, accumulate forces from coincident quadrants.
25147     else {
25148       q = quad;
25149       q.x = q.data.x;
25150       q.y = q.data.y;
25151       do strength += strengths[q.data.index];
25152       while (q = q.next);
25153     }
25154
25155     quad.value = strength;
25156   }
25157
25158   function apply(quad, x1, _, x2) {
25159     if (!quad.value) return true;
25160
25161     var x$$1 = quad.x - node.x,
25162         y$$1 = quad.y - node.y,
25163         w = x2 - x1,
25164         l = x$$1 * x$$1 + y$$1 * y$$1;
25165
25166     // Apply the Barnes-Hut approximation if possible.
25167     // Limit forces for very close nodes; randomize direction if coincident.
25168     if (w * w / theta2 < l) {
25169       if (l < distanceMax2) {
25170         if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25171         if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25172         if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25173         node.vx += x$$1 * quad.value * alpha / l;
25174         node.vy += y$$1 * quad.value * alpha / l;
25175       }
25176       return true;
25177     }
25178
25179     // Otherwise, process points directly.
25180     else if (quad.length || l >= distanceMax2) return;
25181
25182     // Limit forces for very close nodes; randomize direction if coincident.
25183     if (quad.data !== node || quad.next) {
25184       if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
25185       if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
25186       if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
25187     }
25188
25189     do if (quad.data !== node) {
25190       w = strengths[quad.data.index] * alpha / l;
25191       node.vx += x$$1 * w;
25192       node.vy += y$$1 * w;
25193     } while (quad = quad.next);
25194   }
25195
25196   force.initialize = function(_) {
25197     nodes = _;
25198     initialize();
25199   };
25200
25201   force.strength = function(_) {
25202     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25203   };
25204
25205   force.distanceMin = function(_) {
25206     return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
25207   };
25208
25209   force.distanceMax = function(_) {
25210     return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
25211   };
25212
25213   force.theta = function(_) {
25214     return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
25215   };
25216
25217   return force;
25218 };
25219
25220 var x$2 = function(x) {
25221   var strength = constant$6(0.1),
25222       nodes,
25223       strengths,
25224       xz;
25225
25226   if (typeof x !== "function") x = constant$6(x == null ? 0 : +x);
25227
25228   function force(alpha) {
25229     for (var i = 0, n = nodes.length, node; i < n; ++i) {
25230       node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
25231     }
25232   }
25233
25234   function initialize() {
25235     if (!nodes) return;
25236     var i, n = nodes.length;
25237     strengths = new Array(n);
25238     xz = new Array(n);
25239     for (i = 0; i < n; ++i) {
25240       strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25241     }
25242   }
25243
25244   force.initialize = function(_) {
25245     nodes = _;
25246     initialize();
25247   };
25248
25249   force.strength = function(_) {
25250     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25251   };
25252
25253   force.x = function(_) {
25254     return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x;
25255   };
25256
25257   return force;
25258 };
25259
25260 var y$2 = function(y) {
25261   var strength = constant$6(0.1),
25262       nodes,
25263       strengths,
25264       yz;
25265
25266   if (typeof y !== "function") y = constant$6(y == null ? 0 : +y);
25267
25268   function force(alpha) {
25269     for (var i = 0, n = nodes.length, node; i < n; ++i) {
25270       node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
25271     }
25272   }
25273
25274   function initialize() {
25275     if (!nodes) return;
25276     var i, n = nodes.length;
25277     strengths = new Array(n);
25278     yz = new Array(n);
25279     for (i = 0; i < n; ++i) {
25280       strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
25281     }
25282   }
25283
25284   force.initialize = function(_) {
25285     nodes = _;
25286     initialize();
25287   };
25288
25289   force.strength = function(_) {
25290     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength;
25291   };
25292
25293   force.y = function(_) {
25294     return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y;
25295   };
25296
25297   return force;
25298 };
25299
25300 // Computes the decimal coefficient and exponent of the specified number x with
25301 // significant digits p, where x is positive and p is in [1, 21] or undefined.
25302 // For example, formatDecimal(1.23) returns ["123", 0].
25303 var formatDecimal = function(x, p) {
25304   if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
25305   var i, coefficient = x.slice(0, i);
25306
25307   // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
25308   // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
25309   return [
25310     coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
25311     +x.slice(i + 1)
25312   ];
25313 };
25314
25315 var exponent$1 = function(x) {
25316   return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
25317 };
25318
25319 var formatGroup = function(grouping, thousands) {
25320   return function(value, width) {
25321     var i = value.length,
25322         t = [],
25323         j = 0,
25324         g = grouping[0],
25325         length = 0;
25326
25327     while (i > 0 && g > 0) {
25328       if (length + g + 1 > width) g = Math.max(1, width - length);
25329       t.push(value.substring(i -= g, i + g));
25330       if ((length += g + 1) > width) break;
25331       g = grouping[j = (j + 1) % grouping.length];
25332     }
25333
25334     return t.reverse().join(thousands);
25335   };
25336 };
25337
25338 var formatDefault = function(x, p) {
25339   x = x.toPrecision(p);
25340
25341   out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
25342     switch (x[i]) {
25343       case ".": i0 = i1 = i; break;
25344       case "0": if (i0 === 0) i0 = i; i1 = i; break;
25345       case "e": break out;
25346       default: if (i0 > 0) i0 = 0; break;
25347     }
25348   }
25349
25350   return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
25351 };
25352
25353 var prefixExponent;
25354
25355 var formatPrefixAuto = function(x, p) {
25356   var d = formatDecimal(x, p);
25357   if (!d) return x + "";
25358   var coefficient = d[0],
25359       exponent = d[1],
25360       i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
25361       n = coefficient.length;
25362   return i === n ? coefficient
25363       : i > n ? coefficient + new Array(i - n + 1).join("0")
25364       : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
25365       : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
25366 };
25367
25368 var formatRounded = function(x, p) {
25369   var d = formatDecimal(x, p);
25370   if (!d) return x + "";
25371   var coefficient = d[0],
25372       exponent = d[1];
25373   return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
25374       : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
25375       : coefficient + new Array(exponent - coefficient.length + 2).join("0");
25376 };
25377
25378 var formatTypes = {
25379   "": formatDefault,
25380   "%": function(x, p) { return (x * 100).toFixed(p); },
25381   "b": function(x) { return Math.round(x).toString(2); },
25382   "c": function(x) { return x + ""; },
25383   "d": function(x) { return Math.round(x).toString(10); },
25384   "e": function(x, p) { return x.toExponential(p); },
25385   "f": function(x, p) { return x.toFixed(p); },
25386   "g": function(x, p) { return x.toPrecision(p); },
25387   "o": function(x) { return Math.round(x).toString(8); },
25388   "p": function(x, p) { return formatRounded(x * 100, p); },
25389   "r": formatRounded,
25390   "s": formatPrefixAuto,
25391   "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
25392   "x": function(x) { return Math.round(x).toString(16); }
25393 };
25394
25395 // [[fill]align][sign][symbol][0][width][,][.precision][type]
25396 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
25397
25398 var formatSpecifier = function(specifier) {
25399   return new FormatSpecifier(specifier);
25400 };
25401
25402 function FormatSpecifier(specifier) {
25403   if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
25404
25405   var match,
25406       fill = match[1] || " ",
25407       align = match[2] || ">",
25408       sign = match[3] || "-",
25409       symbol = match[4] || "",
25410       zero = !!match[5],
25411       width = match[6] && +match[6],
25412       comma = !!match[7],
25413       precision = match[8] && +match[8].slice(1),
25414       type = match[9] || "";
25415
25416   // The "n" type is an alias for ",g".
25417   if (type === "n") comma = true, type = "g";
25418
25419   // Map invalid types to the default format.
25420   else if (!formatTypes[type]) type = "";
25421
25422   // If zero fill is specified, padding goes after sign and before digits.
25423   if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
25424
25425   this.fill = fill;
25426   this.align = align;
25427   this.sign = sign;
25428   this.symbol = symbol;
25429   this.zero = zero;
25430   this.width = width;
25431   this.comma = comma;
25432   this.precision = precision;
25433   this.type = type;
25434 }
25435
25436 FormatSpecifier.prototype.toString = function() {
25437   return this.fill
25438       + this.align
25439       + this.sign
25440       + this.symbol
25441       + (this.zero ? "0" : "")
25442       + (this.width == null ? "" : Math.max(1, this.width | 0))
25443       + (this.comma ? "," : "")
25444       + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
25445       + this.type;
25446 };
25447
25448 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
25449
25450 function identity$3(x) {
25451   return x;
25452 }
25453
25454 var formatLocale = function(locale) {
25455   var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
25456       currency = locale.currency,
25457       decimal = locale.decimal;
25458
25459   function newFormat(specifier) {
25460     specifier = formatSpecifier(specifier);
25461
25462     var fill = specifier.fill,
25463         align = specifier.align,
25464         sign = specifier.sign,
25465         symbol = specifier.symbol,
25466         zero = specifier.zero,
25467         width = specifier.width,
25468         comma = specifier.comma,
25469         precision = specifier.precision,
25470         type = specifier.type;
25471
25472     // Compute the prefix and suffix.
25473     // For SI-prefix, the suffix is lazily computed.
25474     var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
25475         suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
25476
25477     // What format function should we use?
25478     // Is this an integer type?
25479     // Can this type generate exponential notation?
25480     var formatType = formatTypes[type],
25481         maybeSuffix = !type || /[defgprs%]/.test(type);
25482
25483     // Set the default precision if not specified,
25484     // or clamp the specified precision to the supported range.
25485     // For significant precision, it must be in [1, 21].
25486     // For fixed precision, it must be in [0, 20].
25487     precision = precision == null ? (type ? 6 : 12)
25488         : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
25489         : Math.max(0, Math.min(20, precision));
25490
25491     function format(value) {
25492       var valuePrefix = prefix,
25493           valueSuffix = suffix,
25494           i, n, c;
25495
25496       if (type === "c") {
25497         valueSuffix = formatType(value) + valueSuffix;
25498         value = "";
25499       } else {
25500         value = +value;
25501
25502         // Convert negative to positive, and compute the prefix.
25503         // Note that -0 is not less than 0, but 1 / -0 is!
25504         var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
25505
25506         // Perform the initial formatting.
25507         value = formatType(value, precision);
25508
25509         // If the original value was negative, it may be rounded to zero during
25510         // formatting; treat this as (positive) zero.
25511         if (valueNegative) {
25512           i = -1, n = value.length;
25513           valueNegative = false;
25514           while (++i < n) {
25515             if (c = value.charCodeAt(i), (48 < c && c < 58)
25516                 || (type === "x" && 96 < c && c < 103)
25517                 || (type === "X" && 64 < c && c < 71)) {
25518               valueNegative = true;
25519               break;
25520             }
25521           }
25522         }
25523
25524         // Compute the prefix and suffix.
25525         valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
25526         valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
25527
25528         // Break the formatted value into the integer “value” part that can be
25529         // grouped, and fractional or exponential “suffix” part that is not.
25530         if (maybeSuffix) {
25531           i = -1, n = value.length;
25532           while (++i < n) {
25533             if (c = value.charCodeAt(i), 48 > c || c > 57) {
25534               valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
25535               value = value.slice(0, i);
25536               break;
25537             }
25538           }
25539         }
25540       }
25541
25542       // If the fill character is not "0", grouping is applied before padding.
25543       if (comma && !zero) value = group(value, Infinity);
25544
25545       // Compute the padding.
25546       var length = valuePrefix.length + value.length + valueSuffix.length,
25547           padding = length < width ? new Array(width - length + 1).join(fill) : "";
25548
25549       // If the fill character is "0", grouping is applied after padding.
25550       if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
25551
25552       // Reconstruct the final output based on the desired alignment.
25553       switch (align) {
25554         case "<": return valuePrefix + value + valueSuffix + padding;
25555         case "=": return valuePrefix + padding + value + valueSuffix;
25556         case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
25557       }
25558       return padding + valuePrefix + value + valueSuffix;
25559     }
25560
25561     format.toString = function() {
25562       return specifier + "";
25563     };
25564
25565     return format;
25566   }
25567
25568   function formatPrefix(specifier, value) {
25569     var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
25570         e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
25571         k = Math.pow(10, -e),
25572         prefix = prefixes[8 + e / 3];
25573     return function(value) {
25574       return f(k * value) + prefix;
25575     };
25576   }
25577
25578   return {
25579     format: newFormat,
25580     formatPrefix: formatPrefix
25581   };
25582 };
25583
25584 var locale$1;
25585 var format;
25586 var formatPrefix;
25587
25588 defaultLocale({
25589   decimal: ".",
25590   thousands: ",",
25591   grouping: [3],
25592   currency: ["$", ""]
25593 });
25594
25595 function defaultLocale(definition) {
25596   locale$1 = formatLocale(definition);
25597   format = locale$1.format;
25598   formatPrefix = locale$1.formatPrefix;
25599   return locale$1;
25600 }
25601
25602 var precisionFixed = function(step) {
25603   return Math.max(0, -exponent$1(Math.abs(step)));
25604 };
25605
25606 var precisionPrefix = function(step, value) {
25607   return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
25608 };
25609
25610 var precisionRound = function(step, max) {
25611   step = Math.abs(step), max = Math.abs(max) - step;
25612   return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
25613 };
25614
25615 // Adds floating point numbers with twice the normal precision.
25616 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
25617 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
25618 // 305–363 (1997).
25619 // Code adapted from GeographicLib by Charles F. F. Karney,
25620 // http://geographiclib.sourceforge.net/
25621
25622 var adder = function() {
25623   return new Adder;
25624 };
25625
25626 function Adder() {
25627   this.reset();
25628 }
25629
25630 Adder.prototype = {
25631   constructor: Adder,
25632   reset: function() {
25633     this.s = // rounded value
25634     this.t = 0; // exact error
25635   },
25636   add: function(y) {
25637     add$1(temp, y, this.t);
25638     add$1(this, temp.s, this.s);
25639     if (this.s) this.t += temp.t;
25640     else this.s = temp.t;
25641   },
25642   valueOf: function() {
25643     return this.s;
25644   }
25645 };
25646
25647 var temp = new Adder;
25648
25649 function add$1(adder, a, b) {
25650   var x = adder.s = a + b,
25651       bv = x - a,
25652       av = x - bv;
25653   adder.t = (a - av) + (b - bv);
25654 }
25655
25656 var epsilon$2 = 1e-6;
25657 var epsilon2$1 = 1e-12;
25658 var pi$3 = Math.PI;
25659 var halfPi$2 = pi$3 / 2;
25660 var quarterPi = pi$3 / 4;
25661 var tau$3 = pi$3 * 2;
25662
25663 var degrees$1 = 180 / pi$3;
25664 var radians = pi$3 / 180;
25665
25666 var abs = Math.abs;
25667 var atan = Math.atan;
25668 var atan2 = Math.atan2;
25669 var cos$1 = Math.cos;
25670 var ceil = Math.ceil;
25671 var exp = Math.exp;
25672
25673 var log = Math.log;
25674 var pow = Math.pow;
25675 var sin$1 = Math.sin;
25676 var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
25677 var sqrt = Math.sqrt;
25678 var tan = Math.tan;
25679
25680 function acos(x) {
25681   return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x);
25682 }
25683
25684 function asin(x) {
25685   return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x);
25686 }
25687
25688 function haversin(x) {
25689   return (x = sin$1(x / 2)) * x;
25690 }
25691
25692 function noop$1() {}
25693
25694 function streamGeometry(geometry, stream) {
25695   if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
25696     streamGeometryType[geometry.type](geometry, stream);
25697   }
25698 }
25699
25700 var streamObjectType = {
25701   Feature: function(feature, stream) {
25702     streamGeometry(feature.geometry, stream);
25703   },
25704   FeatureCollection: function(object, stream) {
25705     var features = object.features, i = -1, n = features.length;
25706     while (++i < n) streamGeometry(features[i].geometry, stream);
25707   }
25708 };
25709
25710 var streamGeometryType = {
25711   Sphere: function(object, stream) {
25712     stream.sphere();
25713   },
25714   Point: function(object, stream) {
25715     object = object.coordinates;
25716     stream.point(object[0], object[1], object[2]);
25717   },
25718   MultiPoint: function(object, stream) {
25719     var coordinates = object.coordinates, i = -1, n = coordinates.length;
25720     while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
25721   },
25722   LineString: function(object, stream) {
25723     streamLine(object.coordinates, stream, 0);
25724   },
25725   MultiLineString: function(object, stream) {
25726     var coordinates = object.coordinates, i = -1, n = coordinates.length;
25727     while (++i < n) streamLine(coordinates[i], stream, 0);
25728   },
25729   Polygon: function(object, stream) {
25730     streamPolygon(object.coordinates, stream);
25731   },
25732   MultiPolygon: function(object, stream) {
25733     var coordinates = object.coordinates, i = -1, n = coordinates.length;
25734     while (++i < n) streamPolygon(coordinates[i], stream);
25735   },
25736   GeometryCollection: function(object, stream) {
25737     var geometries = object.geometries, i = -1, n = geometries.length;
25738     while (++i < n) streamGeometry(geometries[i], stream);
25739   }
25740 };
25741
25742 function streamLine(coordinates, stream, closed) {
25743   var i = -1, n = coordinates.length - closed, coordinate;
25744   stream.lineStart();
25745   while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
25746   stream.lineEnd();
25747 }
25748
25749 function streamPolygon(coordinates, stream) {
25750   var i = -1, n = coordinates.length;
25751   stream.polygonStart();
25752   while (++i < n) streamLine(coordinates[i], stream, 1);
25753   stream.polygonEnd();
25754 }
25755
25756 var geoStream = function(object, stream) {
25757   if (object && streamObjectType.hasOwnProperty(object.type)) {
25758     streamObjectType[object.type](object, stream);
25759   } else {
25760     streamGeometry(object, stream);
25761   }
25762 };
25763
25764 var areaRingSum = adder();
25765
25766 var areaSum = adder();
25767 var lambda00;
25768 var phi00;
25769 var lambda0;
25770 var cosPhi0;
25771 var sinPhi0;
25772
25773 var areaStream = {
25774   point: noop$1,
25775   lineStart: noop$1,
25776   lineEnd: noop$1,
25777   polygonStart: function() {
25778     areaRingSum.reset();
25779     areaStream.lineStart = areaRingStart;
25780     areaStream.lineEnd = areaRingEnd;
25781   },
25782   polygonEnd: function() {
25783     var areaRing = +areaRingSum;
25784     areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing);
25785     this.lineStart = this.lineEnd = this.point = noop$1;
25786   },
25787   sphere: function() {
25788     areaSum.add(tau$3);
25789   }
25790 };
25791
25792 function areaRingStart() {
25793   areaStream.point = areaPointFirst;
25794 }
25795
25796 function areaRingEnd() {
25797   areaPoint(lambda00, phi00);
25798 }
25799
25800 function areaPointFirst(lambda, phi) {
25801   areaStream.point = areaPoint;
25802   lambda00 = lambda, phi00 = phi;
25803   lambda *= radians, phi *= radians;
25804   lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
25805 }
25806
25807 function areaPoint(lambda, phi) {
25808   lambda *= radians, phi *= radians;
25809   phi = phi / 2 + quarterPi; // half the angular distance from south pole
25810
25811   // Spherical excess E for a spherical triangle with vertices: south pole,
25812   // previous point, current point.  Uses a formula derived from Cagnoli’s
25813   // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
25814   var dLambda = lambda - lambda0,
25815       sdLambda = dLambda >= 0 ? 1 : -1,
25816       adLambda = sdLambda * dLambda,
25817       cosPhi = cos$1(phi),
25818       sinPhi = sin$1(phi),
25819       k = sinPhi0 * sinPhi,
25820       u = cosPhi0 * cosPhi + k * cos$1(adLambda),
25821       v = k * sdLambda * sin$1(adLambda);
25822   areaRingSum.add(atan2(v, u));
25823
25824   // Advance the previous points.
25825   lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
25826 }
25827
25828 var area = function(object) {
25829   areaSum.reset();
25830   geoStream(object, areaStream);
25831   return areaSum * 2;
25832 };
25833
25834 function spherical(cartesian) {
25835   return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
25836 }
25837
25838 function cartesian(spherical) {
25839   var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
25840   return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
25841 }
25842
25843 function cartesianDot(a, b) {
25844   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
25845 }
25846
25847 function cartesianCross(a, b) {
25848   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]];
25849 }
25850
25851 // TODO return a
25852 function cartesianAddInPlace(a, b) {
25853   a[0] += b[0], a[1] += b[1], a[2] += b[2];
25854 }
25855
25856 function cartesianScale(vector, k) {
25857   return [vector[0] * k, vector[1] * k, vector[2] * k];
25858 }
25859
25860 // TODO return d
25861 function cartesianNormalizeInPlace(d) {
25862   var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
25863   d[0] /= l, d[1] /= l, d[2] /= l;
25864 }
25865
25866 var lambda0$1;
25867 var phi0;
25868 var lambda1;
25869 var phi1;
25870 var lambda2;
25871 var lambda00$1;
25872 var phi00$1;
25873 var p0;
25874 var deltaSum = adder();
25875 var ranges;
25876 var range;
25877
25878 var boundsStream = {
25879   point: boundsPoint,
25880   lineStart: boundsLineStart,
25881   lineEnd: boundsLineEnd,
25882   polygonStart: function() {
25883     boundsStream.point = boundsRingPoint;
25884     boundsStream.lineStart = boundsRingStart;
25885     boundsStream.lineEnd = boundsRingEnd;
25886     deltaSum.reset();
25887     areaStream.polygonStart();
25888   },
25889   polygonEnd: function() {
25890     areaStream.polygonEnd();
25891     boundsStream.point = boundsPoint;
25892     boundsStream.lineStart = boundsLineStart;
25893     boundsStream.lineEnd = boundsLineEnd;
25894     if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
25895     else if (deltaSum > epsilon$2) phi1 = 90;
25896     else if (deltaSum < -epsilon$2) phi0 = -90;
25897     range[0] = lambda0$1, range[1] = lambda1;
25898   }
25899 };
25900
25901 function boundsPoint(lambda, phi) {
25902   ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
25903   if (phi < phi0) phi0 = phi;
25904   if (phi > phi1) phi1 = phi;
25905 }
25906
25907 function linePoint(lambda, phi) {
25908   var p = cartesian([lambda * radians, phi * radians]);
25909   if (p0) {
25910     var normal = cartesianCross(p0, p),
25911         equatorial = [normal[1], -normal[0], 0],
25912         inflection = cartesianCross(equatorial, normal);
25913     cartesianNormalizeInPlace(inflection);
25914     inflection = spherical(inflection);
25915     var delta = lambda - lambda2,
25916         sign$$1 = delta > 0 ? 1 : -1,
25917         lambdai = inflection[0] * degrees$1 * sign$$1,
25918         phii,
25919         antimeridian = abs(delta) > 180;
25920     if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
25921       phii = inflection[1] * degrees$1;
25922       if (phii > phi1) phi1 = phii;
25923     } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
25924       phii = -inflection[1] * degrees$1;
25925       if (phii < phi0) phi0 = phii;
25926     } else {
25927       if (phi < phi0) phi0 = phi;
25928       if (phi > phi1) phi1 = phi;
25929     }
25930     if (antimeridian) {
25931       if (lambda < lambda2) {
25932         if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
25933       } else {
25934         if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
25935       }
25936     } else {
25937       if (lambda1 >= lambda0$1) {
25938         if (lambda < lambda0$1) lambda0$1 = lambda;
25939         if (lambda > lambda1) lambda1 = lambda;
25940       } else {
25941         if (lambda > lambda2) {
25942           if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
25943         } else {
25944           if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
25945         }
25946       }
25947     }
25948   } else {
25949     boundsPoint(lambda, phi);
25950   }
25951   p0 = p, lambda2 = lambda;
25952 }
25953
25954 function boundsLineStart() {
25955   boundsStream.point = linePoint;
25956 }
25957
25958 function boundsLineEnd() {
25959   range[0] = lambda0$1, range[1] = lambda1;
25960   boundsStream.point = boundsPoint;
25961   p0 = null;
25962 }
25963
25964 function boundsRingPoint(lambda, phi) {
25965   if (p0) {
25966     var delta = lambda - lambda2;
25967     deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
25968   } else {
25969     lambda00$1 = lambda, phi00$1 = phi;
25970   }
25971   areaStream.point(lambda, phi);
25972   linePoint(lambda, phi);
25973 }
25974
25975 function boundsRingStart() {
25976   areaStream.lineStart();
25977 }
25978
25979 function boundsRingEnd() {
25980   boundsRingPoint(lambda00$1, phi00$1);
25981   areaStream.lineEnd();
25982   if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180);
25983   range[0] = lambda0$1, range[1] = lambda1;
25984   p0 = null;
25985 }
25986
25987 // Finds the left-right distance between two longitudes.
25988 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
25989 // the distance between ±180° to be 360°.
25990 function angle(lambda0, lambda1) {
25991   return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
25992 }
25993
25994 function rangeCompare(a, b) {
25995   return a[0] - b[0];
25996 }
25997
25998 function rangeContains(range, x) {
25999   return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
26000 }
26001
26002 var bounds = function(feature) {
26003   var i, n, a, b, merged, deltaMax, delta;
26004
26005   phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
26006   ranges = [];
26007   geoStream(feature, boundsStream);
26008
26009   // First, sort ranges by their minimum longitudes.
26010   if (n = ranges.length) {
26011     ranges.sort(rangeCompare);
26012
26013     // Then, merge any ranges that overlap.
26014     for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
26015       b = ranges[i];
26016       if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
26017         if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
26018         if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
26019       } else {
26020         merged.push(a = b);
26021       }
26022     }
26023
26024     // Finally, find the largest gap between the merged ranges.
26025     // The final bounding box will be the inverse of this gap.
26026     for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
26027       b = merged[i];
26028       if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
26029     }
26030   }
26031
26032   ranges = range = null;
26033
26034   return lambda0$1 === Infinity || phi0 === Infinity
26035       ? [[NaN, NaN], [NaN, NaN]]
26036       : [[lambda0$1, phi0], [lambda1, phi1]];
26037 };
26038
26039 var W0;
26040 var W1;
26041 var X0;
26042 var Y0;
26043 var Z0;
26044 var X1;
26045 var Y1;
26046 var Z1;
26047 var X2;
26048 var Y2;
26049 var Z2;
26050 var lambda00$2;
26051 var phi00$2;
26052 var x0;
26053 var y0;
26054 var z0; // previous point
26055
26056 var centroidStream = {
26057   sphere: noop$1,
26058   point: centroidPoint,
26059   lineStart: centroidLineStart,
26060   lineEnd: centroidLineEnd,
26061   polygonStart: function() {
26062     centroidStream.lineStart = centroidRingStart;
26063     centroidStream.lineEnd = centroidRingEnd;
26064   },
26065   polygonEnd: function() {
26066     centroidStream.lineStart = centroidLineStart;
26067     centroidStream.lineEnd = centroidLineEnd;
26068   }
26069 };
26070
26071 // Arithmetic mean of Cartesian vectors.
26072 function centroidPoint(lambda, phi) {
26073   lambda *= radians, phi *= radians;
26074   var cosPhi = cos$1(phi);
26075   centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
26076 }
26077
26078 function centroidPointCartesian(x, y, z) {
26079   ++W0;
26080   X0 += (x - X0) / W0;
26081   Y0 += (y - Y0) / W0;
26082   Z0 += (z - Z0) / W0;
26083 }
26084
26085 function centroidLineStart() {
26086   centroidStream.point = centroidLinePointFirst;
26087 }
26088
26089 function centroidLinePointFirst(lambda, phi) {
26090   lambda *= radians, phi *= radians;
26091   var cosPhi = cos$1(phi);
26092   x0 = cosPhi * cos$1(lambda);
26093   y0 = cosPhi * sin$1(lambda);
26094   z0 = sin$1(phi);
26095   centroidStream.point = centroidLinePoint;
26096   centroidPointCartesian(x0, y0, z0);
26097 }
26098
26099 function centroidLinePoint(lambda, phi) {
26100   lambda *= radians, phi *= radians;
26101   var cosPhi = cos$1(phi),
26102       x = cosPhi * cos$1(lambda),
26103       y = cosPhi * sin$1(lambda),
26104       z = sin$1(phi),
26105       w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
26106   W1 += w;
26107   X1 += w * (x0 + (x0 = x));
26108   Y1 += w * (y0 + (y0 = y));
26109   Z1 += w * (z0 + (z0 = z));
26110   centroidPointCartesian(x0, y0, z0);
26111 }
26112
26113 function centroidLineEnd() {
26114   centroidStream.point = centroidPoint;
26115 }
26116
26117 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
26118 // J. Applied Mechanics 42, 239 (1975).
26119 function centroidRingStart() {
26120   centroidStream.point = centroidRingPointFirst;
26121 }
26122
26123 function centroidRingEnd() {
26124   centroidRingPoint(lambda00$2, phi00$2);
26125   centroidStream.point = centroidPoint;
26126 }
26127
26128 function centroidRingPointFirst(lambda, phi) {
26129   lambda00$2 = lambda, phi00$2 = phi;
26130   lambda *= radians, phi *= radians;
26131   centroidStream.point = centroidRingPoint;
26132   var cosPhi = cos$1(phi);
26133   x0 = cosPhi * cos$1(lambda);
26134   y0 = cosPhi * sin$1(lambda);
26135   z0 = sin$1(phi);
26136   centroidPointCartesian(x0, y0, z0);
26137 }
26138
26139 function centroidRingPoint(lambda, phi) {
26140   lambda *= radians, phi *= radians;
26141   var cosPhi = cos$1(phi),
26142       x = cosPhi * cos$1(lambda),
26143       y = cosPhi * sin$1(lambda),
26144       z = sin$1(phi),
26145       cx = y0 * z - z0 * y,
26146       cy = z0 * x - x0 * z,
26147       cz = x0 * y - y0 * x,
26148       m = sqrt(cx * cx + cy * cy + cz * cz),
26149       u = x0 * x + y0 * y + z0 * z,
26150       v = m && -acos(u) / m, // area weight
26151       w = atan2(m, u); // line weight
26152   X2 += v * cx;
26153   Y2 += v * cy;
26154   Z2 += v * cz;
26155   W1 += w;
26156   X1 += w * (x0 + (x0 = x));
26157   Y1 += w * (y0 + (y0 = y));
26158   Z1 += w * (z0 + (z0 = z));
26159   centroidPointCartesian(x0, y0, z0);
26160 }
26161
26162 var d3GeoCentroid = function(object) {
26163   W0 = W1 =
26164   X0 = Y0 = Z0 =
26165   X1 = Y1 = Z1 =
26166   X2 = Y2 = Z2 = 0;
26167   geoStream(object, centroidStream);
26168
26169   var x = X2,
26170       y = Y2,
26171       z = Z2,
26172       m = x * x + y * y + z * z;
26173
26174   // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
26175   if (m < epsilon2$1) {
26176     x = X1, y = Y1, z = Z1;
26177     // If the feature has zero length, fall back to arithmetic mean of point vectors.
26178     if (W1 < epsilon$2) x = X0, y = Y0, z = Z0;
26179     m = x * x + y * y + z * z;
26180     // If the feature still has an undefined ccentroid, then return.
26181     if (m < epsilon2$1) return [NaN, NaN];
26182   }
26183
26184   return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1];
26185 };
26186
26187 var constant$7 = function(x) {
26188   return function() {
26189     return x;
26190   };
26191 };
26192
26193 var compose = function(a, b) {
26194
26195   function compose(x, y) {
26196     return x = a(x, y), b(x[0], x[1]);
26197   }
26198
26199   if (a.invert && b.invert) compose.invert = function(x, y) {
26200     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
26201   };
26202
26203   return compose;
26204 };
26205
26206 function rotationIdentity(lambda, phi) {
26207   return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26208 }
26209
26210 rotationIdentity.invert = rotationIdentity;
26211
26212 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
26213   return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
26214     : rotationLambda(deltaLambda))
26215     : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
26216     : rotationIdentity);
26217 }
26218
26219 function forwardRotationLambda(deltaLambda) {
26220   return function(lambda, phi) {
26221     return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi];
26222   };
26223 }
26224
26225 function rotationLambda(deltaLambda) {
26226   var rotation = forwardRotationLambda(deltaLambda);
26227   rotation.invert = forwardRotationLambda(-deltaLambda);
26228   return rotation;
26229 }
26230
26231 function rotationPhiGamma(deltaPhi, deltaGamma) {
26232   var cosDeltaPhi = cos$1(deltaPhi),
26233       sinDeltaPhi = sin$1(deltaPhi),
26234       cosDeltaGamma = cos$1(deltaGamma),
26235       sinDeltaGamma = sin$1(deltaGamma);
26236
26237   function rotation(lambda, phi) {
26238     var cosPhi = cos$1(phi),
26239         x = cos$1(lambda) * cosPhi,
26240         y = sin$1(lambda) * cosPhi,
26241         z = sin$1(phi),
26242         k = z * cosDeltaPhi + x * sinDeltaPhi;
26243     return [
26244       atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
26245       asin(k * cosDeltaGamma + y * sinDeltaGamma)
26246     ];
26247   }
26248
26249   rotation.invert = function(lambda, phi) {
26250     var cosPhi = cos$1(phi),
26251         x = cos$1(lambda) * cosPhi,
26252         y = sin$1(lambda) * cosPhi,
26253         z = sin$1(phi),
26254         k = z * cosDeltaGamma - y * sinDeltaGamma;
26255     return [
26256       atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
26257       asin(k * cosDeltaPhi - x * sinDeltaPhi)
26258     ];
26259   };
26260
26261   return rotation;
26262 }
26263
26264 var rotation = function(rotate) {
26265   rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
26266
26267   function forward(coordinates) {
26268     coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
26269     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26270   }
26271
26272   forward.invert = function(coordinates) {
26273     coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
26274     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
26275   };
26276
26277   return forward;
26278 };
26279
26280 // Generates a circle centered at [0°, 0°], with a given radius and precision.
26281 function circleStream(stream, radius, delta, direction, t0, t1) {
26282   if (!delta) return;
26283   var cosRadius = cos$1(radius),
26284       sinRadius = sin$1(radius),
26285       step = direction * delta;
26286   if (t0 == null) {
26287     t0 = radius + direction * tau$3;
26288     t1 = radius - step / 2;
26289   } else {
26290     t0 = circleRadius(cosRadius, t0);
26291     t1 = circleRadius(cosRadius, t1);
26292     if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3;
26293   }
26294   for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
26295     point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
26296     stream.point(point[0], point[1]);
26297   }
26298 }
26299
26300 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
26301 function circleRadius(cosRadius, point) {
26302   point = cartesian(point), point[0] -= cosRadius;
26303   cartesianNormalizeInPlace(point);
26304   var radius = acos(-point[1]);
26305   return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3;
26306 }
26307
26308 var circle = function() {
26309   var center = constant$7([0, 0]),
26310       radius = constant$7(90),
26311       precision = constant$7(6),
26312       ring,
26313       rotate,
26314       stream = {point: point};
26315
26316   function point(x, y) {
26317     ring.push(x = rotate(x, y));
26318     x[0] *= degrees$1, x[1] *= degrees$1;
26319   }
26320
26321   function circle() {
26322     var c = center.apply(this, arguments),
26323         r = radius.apply(this, arguments) * radians,
26324         p = precision.apply(this, arguments) * radians;
26325     ring = [];
26326     rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
26327     circleStream(stream, r, p, 1);
26328     c = {type: "Polygon", coordinates: [ring]};
26329     ring = rotate = null;
26330     return c;
26331   }
26332
26333   circle.center = function(_) {
26334     return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center;
26335   };
26336
26337   circle.radius = function(_) {
26338     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius;
26339   };
26340
26341   circle.precision = function(_) {
26342     return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision;
26343   };
26344
26345   return circle;
26346 };
26347
26348 var clipBuffer = function() {
26349   var lines = [],
26350       line;
26351   return {
26352     point: function(x, y) {
26353       line.push([x, y]);
26354     },
26355     lineStart: function() {
26356       lines.push(line = []);
26357     },
26358     lineEnd: noop$1,
26359     rejoin: function() {
26360       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
26361     },
26362     result: function() {
26363       var result = lines;
26364       lines = [];
26365       line = null;
26366       return result;
26367     }
26368   };
26369 };
26370
26371 var clipLine = function(a, b, x0, y0, x1, y1) {
26372   var ax = a[0],
26373       ay = a[1],
26374       bx = b[0],
26375       by = b[1],
26376       t0 = 0,
26377       t1 = 1,
26378       dx = bx - ax,
26379       dy = by - ay,
26380       r;
26381
26382   r = x0 - ax;
26383   if (!dx && r > 0) return;
26384   r /= dx;
26385   if (dx < 0) {
26386     if (r < t0) return;
26387     if (r < t1) t1 = r;
26388   } else if (dx > 0) {
26389     if (r > t1) return;
26390     if (r > t0) t0 = r;
26391   }
26392
26393   r = x1 - ax;
26394   if (!dx && r < 0) return;
26395   r /= dx;
26396   if (dx < 0) {
26397     if (r > t1) return;
26398     if (r > t0) t0 = r;
26399   } else if (dx > 0) {
26400     if (r < t0) return;
26401     if (r < t1) t1 = r;
26402   }
26403
26404   r = y0 - ay;
26405   if (!dy && r > 0) return;
26406   r /= dy;
26407   if (dy < 0) {
26408     if (r < t0) return;
26409     if (r < t1) t1 = r;
26410   } else if (dy > 0) {
26411     if (r > t1) return;
26412     if (r > t0) t0 = r;
26413   }
26414
26415   r = y1 - ay;
26416   if (!dy && r < 0) return;
26417   r /= dy;
26418   if (dy < 0) {
26419     if (r > t1) return;
26420     if (r > t0) t0 = r;
26421   } else if (dy > 0) {
26422     if (r < t0) return;
26423     if (r < t1) t1 = r;
26424   }
26425
26426   if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
26427   if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
26428   return true;
26429 };
26430
26431 var pointEqual = function(a, b) {
26432   return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2;
26433 };
26434
26435 function Intersection(point, points, other, entry) {
26436   this.x = point;
26437   this.z = points;
26438   this.o = other; // another intersection
26439   this.e = entry; // is an entry?
26440   this.v = false; // visited
26441   this.n = this.p = null; // next & previous
26442 }
26443
26444 // A generalized polygon clipping algorithm: given a polygon that has been cut
26445 // into its visible line segments, and rejoins the segments by interpolating
26446 // along the clip edge.
26447 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
26448   var subject = [],
26449       clip = [],
26450       i,
26451       n;
26452
26453   segments.forEach(function(segment) {
26454     if ((n = segment.length - 1) <= 0) return;
26455     var n, p0 = segment[0], p1 = segment[n], x;
26456
26457     // If the first and last points of a segment are coincident, then treat as a
26458     // closed ring. TODO if all rings are closed, then the winding order of the
26459     // exterior ring should be checked.
26460     if (pointEqual(p0, p1)) {
26461       stream.lineStart();
26462       for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
26463       stream.lineEnd();
26464       return;
26465     }
26466
26467     subject.push(x = new Intersection(p0, segment, null, true));
26468     clip.push(x.o = new Intersection(p0, null, x, false));
26469     subject.push(x = new Intersection(p1, segment, null, false));
26470     clip.push(x.o = new Intersection(p1, null, x, true));
26471   });
26472
26473   if (!subject.length) return;
26474
26475   clip.sort(compareIntersection);
26476   link$1(subject);
26477   link$1(clip);
26478
26479   for (i = 0, n = clip.length; i < n; ++i) {
26480     clip[i].e = startInside = !startInside;
26481   }
26482
26483   var start = subject[0],
26484       points,
26485       point;
26486
26487   while (1) {
26488     // Find first unvisited intersection.
26489     var current = start,
26490         isSubject = true;
26491     while (current.v) if ((current = current.n) === start) return;
26492     points = current.z;
26493     stream.lineStart();
26494     do {
26495       current.v = current.o.v = true;
26496       if (current.e) {
26497         if (isSubject) {
26498           for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
26499         } else {
26500           interpolate(current.x, current.n.x, 1, stream);
26501         }
26502         current = current.n;
26503       } else {
26504         if (isSubject) {
26505           points = current.p.z;
26506           for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
26507         } else {
26508           interpolate(current.x, current.p.x, -1, stream);
26509         }
26510         current = current.p;
26511       }
26512       current = current.o;
26513       points = current.z;
26514       isSubject = !isSubject;
26515     } while (!current.v);
26516     stream.lineEnd();
26517   }
26518 };
26519
26520 function link$1(array) {
26521   if (!(n = array.length)) return;
26522   var n,
26523       i = 0,
26524       a = array[0],
26525       b;
26526   while (++i < n) {
26527     a.n = b = array[i];
26528     b.p = a;
26529     a = b;
26530   }
26531   a.n = b = array[0];
26532   b.p = a;
26533 }
26534
26535 var clipMax = 1e9;
26536 var clipMin = -clipMax;
26537
26538 // TODO Use d3-polygon’s polygonContains here for the ring check?
26539 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
26540
26541 function clipExtent(x0, y0, x1, y1) {
26542
26543   function visible(x, y) {
26544     return x0 <= x && x <= x1 && y0 <= y && y <= y1;
26545   }
26546
26547   function interpolate(from, to, direction, stream) {
26548     var a = 0, a1 = 0;
26549     if (from == null
26550         || (a = corner(from, direction)) !== (a1 = corner(to, direction))
26551         || comparePoint(from, to) < 0 ^ direction > 0) {
26552       do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
26553       while ((a = (a + direction + 4) % 4) !== a1);
26554     } else {
26555       stream.point(to[0], to[1]);
26556     }
26557   }
26558
26559   function corner(p, direction) {
26560     return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3
26561         : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1
26562         : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0
26563         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
26564   }
26565
26566   function compareIntersection(a, b) {
26567     return comparePoint(a.x, b.x);
26568   }
26569
26570   function comparePoint(a, b) {
26571     var ca = corner(a, 1),
26572         cb = corner(b, 1);
26573     return ca !== cb ? ca - cb
26574         : ca === 0 ? b[1] - a[1]
26575         : ca === 1 ? a[0] - b[0]
26576         : ca === 2 ? a[1] - b[1]
26577         : b[0] - a[0];
26578   }
26579
26580   return function(stream) {
26581     var activeStream = stream,
26582         bufferStream = clipBuffer(),
26583         segments,
26584         polygon,
26585         ring,
26586         x__, y__, v__, // first point
26587         x_, y_, v_, // previous point
26588         first,
26589         clean;
26590
26591     var clipStream = {
26592       point: point,
26593       lineStart: lineStart,
26594       lineEnd: lineEnd,
26595       polygonStart: polygonStart,
26596       polygonEnd: polygonEnd
26597     };
26598
26599     function point(x, y) {
26600       if (visible(x, y)) activeStream.point(x, y);
26601     }
26602
26603     function polygonInside() {
26604       var winding = 0;
26605
26606       for (var i = 0, n = polygon.length; i < n; ++i) {
26607         for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
26608           a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
26609           if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
26610           else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
26611         }
26612       }
26613
26614       return winding;
26615     }
26616
26617     // Buffer geometry within a polygon and then clip it en masse.
26618     function polygonStart() {
26619       activeStream = bufferStream, segments = [], polygon = [], clean = true;
26620     }
26621
26622     function polygonEnd() {
26623       var startInside = polygonInside(),
26624           cleanInside = clean && startInside,
26625           visible = (segments = merge(segments)).length;
26626       if (cleanInside || visible) {
26627         stream.polygonStart();
26628         if (cleanInside) {
26629           stream.lineStart();
26630           interpolate(null, null, 1, stream);
26631           stream.lineEnd();
26632         }
26633         if (visible) {
26634           clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
26635         }
26636         stream.polygonEnd();
26637       }
26638       activeStream = stream, segments = polygon = ring = null;
26639     }
26640
26641     function lineStart() {
26642       clipStream.point = linePoint;
26643       if (polygon) polygon.push(ring = []);
26644       first = true;
26645       v_ = false;
26646       x_ = y_ = NaN;
26647     }
26648
26649     // TODO rather than special-case polygons, simply handle them separately.
26650     // Ideally, coincident intersection points should be jittered to avoid
26651     // clipping issues.
26652     function lineEnd() {
26653       if (segments) {
26654         linePoint(x__, y__);
26655         if (v__ && v_) bufferStream.rejoin();
26656         segments.push(bufferStream.result());
26657       }
26658       clipStream.point = point;
26659       if (v_) activeStream.lineEnd();
26660     }
26661
26662     function linePoint(x, y) {
26663       var v = visible(x, y);
26664       if (polygon) ring.push([x, y]);
26665       if (first) {
26666         x__ = x, y__ = y, v__ = v;
26667         first = false;
26668         if (v) {
26669           activeStream.lineStart();
26670           activeStream.point(x, y);
26671         }
26672       } else {
26673         if (v && v_) activeStream.point(x, y);
26674         else {
26675           var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
26676               b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
26677           if (clipLine(a, b, x0, y0, x1, y1)) {
26678             if (!v_) {
26679               activeStream.lineStart();
26680               activeStream.point(a[0], a[1]);
26681             }
26682             activeStream.point(b[0], b[1]);
26683             if (!v) activeStream.lineEnd();
26684             clean = false;
26685           } else if (v) {
26686             activeStream.lineStart();
26687             activeStream.point(x, y);
26688             clean = false;
26689           }
26690         }
26691       }
26692       x_ = x, y_ = y, v_ = v;
26693     }
26694
26695     return clipStream;
26696   };
26697 }
26698
26699 var extent$1 = function() {
26700   var x0 = 0,
26701       y0 = 0,
26702       x1 = 960,
26703       y1 = 500,
26704       cache,
26705       cacheStream,
26706       clip;
26707
26708   return clip = {
26709     stream: function(stream) {
26710       return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
26711     },
26712     extent: function(_) {
26713       return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
26714     }
26715   };
26716 };
26717
26718 var lengthSum = adder();
26719 var lambda0$2;
26720 var sinPhi0$1;
26721 var cosPhi0$1;
26722
26723 var lengthStream = {
26724   sphere: noop$1,
26725   point: noop$1,
26726   lineStart: lengthLineStart,
26727   lineEnd: noop$1,
26728   polygonStart: noop$1,
26729   polygonEnd: noop$1
26730 };
26731
26732 function lengthLineStart() {
26733   lengthStream.point = lengthPointFirst;
26734   lengthStream.lineEnd = lengthLineEnd;
26735 }
26736
26737 function lengthLineEnd() {
26738   lengthStream.point = lengthStream.lineEnd = noop$1;
26739 }
26740
26741 function lengthPointFirst(lambda, phi) {
26742   lambda *= radians, phi *= radians;
26743   lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
26744   lengthStream.point = lengthPoint;
26745 }
26746
26747 function lengthPoint(lambda, phi) {
26748   lambda *= radians, phi *= radians;
26749   var sinPhi = sin$1(phi),
26750       cosPhi = cos$1(phi),
26751       delta = abs(lambda - lambda0$2),
26752       cosDelta = cos$1(delta),
26753       sinDelta = sin$1(delta),
26754       x = cosPhi * sinDelta,
26755       y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
26756       z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
26757   lengthSum.add(atan2(sqrt(x * x + y * y), z));
26758   lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
26759 }
26760
26761 var d3GeoLength = function(object) {
26762   lengthSum.reset();
26763   geoStream(object, lengthStream);
26764   return +lengthSum;
26765 };
26766
26767 var coordinates = [null, null];
26768 var object$1 = {type: "LineString", coordinates: coordinates};
26769
26770 var distance = function(a, b) {
26771   coordinates[0] = a;
26772   coordinates[1] = b;
26773   return d3GeoLength(object$1);
26774 };
26775
26776 function graticuleX(y0, y1, dy) {
26777   var y = sequence(y0, y1 - epsilon$2, dy).concat(y1);
26778   return function(x) { return y.map(function(y) { return [x, y]; }); };
26779 }
26780
26781 function graticuleY(x0, x1, dx) {
26782   var x = sequence(x0, x1 - epsilon$2, dx).concat(x1);
26783   return function(y) { return x.map(function(x) { return [x, y]; }); };
26784 }
26785
26786 function graticule() {
26787   var x1, x0, X1, X0,
26788       y1, y0, Y1, Y0,
26789       dx = 10, dy = dx, DX = 90, DY = 360,
26790       x, y, X, Y,
26791       precision = 2.5;
26792
26793   function graticule() {
26794     return {type: "MultiLineString", coordinates: lines()};
26795   }
26796
26797   function lines() {
26798     return sequence(ceil(X0 / DX) * DX, X1, DX).map(X)
26799         .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
26800         .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x))
26801         .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y));
26802   }
26803
26804   graticule.lines = function() {
26805     return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
26806   };
26807
26808   graticule.outline = function() {
26809     return {
26810       type: "Polygon",
26811       coordinates: [
26812         X(X0).concat(
26813         Y(Y1).slice(1),
26814         X(X1).reverse().slice(1),
26815         Y(Y0).reverse().slice(1))
26816       ]
26817     };
26818   };
26819
26820   graticule.extent = function(_) {
26821     if (!arguments.length) return graticule.extentMinor();
26822     return graticule.extentMajor(_).extentMinor(_);
26823   };
26824
26825   graticule.extentMajor = function(_) {
26826     if (!arguments.length) return [[X0, Y0], [X1, Y1]];
26827     X0 = +_[0][0], X1 = +_[1][0];
26828     Y0 = +_[0][1], Y1 = +_[1][1];
26829     if (X0 > X1) _ = X0, X0 = X1, X1 = _;
26830     if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
26831     return graticule.precision(precision);
26832   };
26833
26834   graticule.extentMinor = function(_) {
26835     if (!arguments.length) return [[x0, y0], [x1, y1]];
26836     x0 = +_[0][0], x1 = +_[1][0];
26837     y0 = +_[0][1], y1 = +_[1][1];
26838     if (x0 > x1) _ = x0, x0 = x1, x1 = _;
26839     if (y0 > y1) _ = y0, y0 = y1, y1 = _;
26840     return graticule.precision(precision);
26841   };
26842
26843   graticule.step = function(_) {
26844     if (!arguments.length) return graticule.stepMinor();
26845     return graticule.stepMajor(_).stepMinor(_);
26846   };
26847
26848   graticule.stepMajor = function(_) {
26849     if (!arguments.length) return [DX, DY];
26850     DX = +_[0], DY = +_[1];
26851     return graticule;
26852   };
26853
26854   graticule.stepMinor = function(_) {
26855     if (!arguments.length) return [dx, dy];
26856     dx = +_[0], dy = +_[1];
26857     return graticule;
26858   };
26859
26860   graticule.precision = function(_) {
26861     if (!arguments.length) return precision;
26862     precision = +_;
26863     x = graticuleX(y0, y1, 90);
26864     y = graticuleY(x0, x1, precision);
26865     X = graticuleX(Y0, Y1, 90);
26866     Y = graticuleY(X0, X1, precision);
26867     return graticule;
26868   };
26869
26870   return graticule
26871       .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]])
26872       .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]);
26873 }
26874
26875 function graticule10() {
26876   return graticule()();
26877 }
26878
26879 var interpolate$1 = function(a, b) {
26880   var x0 = a[0] * radians,
26881       y0 = a[1] * radians,
26882       x1 = b[0] * radians,
26883       y1 = b[1] * radians,
26884       cy0 = cos$1(y0),
26885       sy0 = sin$1(y0),
26886       cy1 = cos$1(y1),
26887       sy1 = sin$1(y1),
26888       kx0 = cy0 * cos$1(x0),
26889       ky0 = cy0 * sin$1(x0),
26890       kx1 = cy1 * cos$1(x1),
26891       ky1 = cy1 * sin$1(x1),
26892       d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
26893       k = sin$1(d);
26894
26895   var interpolate = d ? function(t) {
26896     var B = sin$1(t *= d) / k,
26897         A = sin$1(d - t) / k,
26898         x = A * kx0 + B * kx1,
26899         y = A * ky0 + B * ky1,
26900         z = A * sy0 + B * sy1;
26901     return [
26902       atan2(y, x) * degrees$1,
26903       atan2(z, sqrt(x * x + y * y)) * degrees$1
26904     ];
26905   } : function() {
26906     return [x0 * degrees$1, y0 * degrees$1];
26907   };
26908
26909   interpolate.distance = d;
26910
26911   return interpolate;
26912 };
26913
26914 var identity$4 = function(x) {
26915   return x;
26916 };
26917
26918 var areaSum$1 = adder();
26919 var areaRingSum$1 = adder();
26920 var x00;
26921 var y00;
26922 var x0$1;
26923 var y0$1;
26924
26925 var areaStream$1 = {
26926   point: noop$1,
26927   lineStart: noop$1,
26928   lineEnd: noop$1,
26929   polygonStart: function() {
26930     areaStream$1.lineStart = areaRingStart$1;
26931     areaStream$1.lineEnd = areaRingEnd$1;
26932   },
26933   polygonEnd: function() {
26934     areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1;
26935     areaSum$1.add(abs(areaRingSum$1));
26936     areaRingSum$1.reset();
26937   },
26938   result: function() {
26939     var area = areaSum$1 / 2;
26940     areaSum$1.reset();
26941     return area;
26942   }
26943 };
26944
26945 function areaRingStart$1() {
26946   areaStream$1.point = areaPointFirst$1;
26947 }
26948
26949 function areaPointFirst$1(x, y) {
26950   areaStream$1.point = areaPoint$1;
26951   x00 = x0$1 = x, y00 = y0$1 = y;
26952 }
26953
26954 function areaPoint$1(x, y) {
26955   areaRingSum$1.add(y0$1 * x - x0$1 * y);
26956   x0$1 = x, y0$1 = y;
26957 }
26958
26959 function areaRingEnd$1() {
26960   areaPoint$1(x00, y00);
26961 }
26962
26963 var x0$2 = Infinity;
26964 var y0$2 = x0$2;
26965 var x1 = -x0$2;
26966 var y1 = x1;
26967
26968 var boundsStream$1 = {
26969   point: boundsPoint$1,
26970   lineStart: noop$1,
26971   lineEnd: noop$1,
26972   polygonStart: noop$1,
26973   polygonEnd: noop$1,
26974   result: function() {
26975     var bounds = [[x0$2, y0$2], [x1, y1]];
26976     x1 = y1 = -(y0$2 = x0$2 = Infinity);
26977     return bounds;
26978   }
26979 };
26980
26981 function boundsPoint$1(x, y) {
26982   if (x < x0$2) x0$2 = x;
26983   if (x > x1) x1 = x;
26984   if (y < y0$2) y0$2 = y;
26985   if (y > y1) y1 = y;
26986 }
26987
26988 // TODO Enforce positive area for exterior, negative area for interior?
26989
26990 var X0$1 = 0;
26991 var Y0$1 = 0;
26992 var Z0$1 = 0;
26993 var X1$1 = 0;
26994 var Y1$1 = 0;
26995 var Z1$1 = 0;
26996 var X2$1 = 0;
26997 var Y2$1 = 0;
26998 var Z2$1 = 0;
26999 var x00$1;
27000 var y00$1;
27001 var x0$3;
27002 var y0$3;
27003
27004 var centroidStream$1 = {
27005   point: centroidPoint$1,
27006   lineStart: centroidLineStart$1,
27007   lineEnd: centroidLineEnd$1,
27008   polygonStart: function() {
27009     centroidStream$1.lineStart = centroidRingStart$1;
27010     centroidStream$1.lineEnd = centroidRingEnd$1;
27011   },
27012   polygonEnd: function() {
27013     centroidStream$1.point = centroidPoint$1;
27014     centroidStream$1.lineStart = centroidLineStart$1;
27015     centroidStream$1.lineEnd = centroidLineEnd$1;
27016   },
27017   result: function() {
27018     var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
27019         : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
27020         : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
27021         : [NaN, NaN];
27022     X0$1 = Y0$1 = Z0$1 =
27023     X1$1 = Y1$1 = Z1$1 =
27024     X2$1 = Y2$1 = Z2$1 = 0;
27025     return centroid;
27026   }
27027 };
27028
27029 function centroidPoint$1(x, y) {
27030   X0$1 += x;
27031   Y0$1 += y;
27032   ++Z0$1;
27033 }
27034
27035 function centroidLineStart$1() {
27036   centroidStream$1.point = centroidPointFirstLine;
27037 }
27038
27039 function centroidPointFirstLine(x, y) {
27040   centroidStream$1.point = centroidPointLine;
27041   centroidPoint$1(x0$3 = x, y0$3 = y);
27042 }
27043
27044 function centroidPointLine(x, y) {
27045   var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy);
27046   X1$1 += z * (x0$3 + x) / 2;
27047   Y1$1 += z * (y0$3 + y) / 2;
27048   Z1$1 += z;
27049   centroidPoint$1(x0$3 = x, y0$3 = y);
27050 }
27051
27052 function centroidLineEnd$1() {
27053   centroidStream$1.point = centroidPoint$1;
27054 }
27055
27056 function centroidRingStart$1() {
27057   centroidStream$1.point = centroidPointFirstRing;
27058 }
27059
27060 function centroidRingEnd$1() {
27061   centroidPointRing(x00$1, y00$1);
27062 }
27063
27064 function centroidPointFirstRing(x, y) {
27065   centroidStream$1.point = centroidPointRing;
27066   centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
27067 }
27068
27069 function centroidPointRing(x, y) {
27070   var dx = x - x0$3,
27071       dy = y - y0$3,
27072       z = sqrt(dx * dx + dy * dy);
27073
27074   X1$1 += z * (x0$3 + x) / 2;
27075   Y1$1 += z * (y0$3 + y) / 2;
27076   Z1$1 += z;
27077
27078   z = y0$3 * x - x0$3 * y;
27079   X2$1 += z * (x0$3 + x);
27080   Y2$1 += z * (y0$3 + y);
27081   Z2$1 += z * 3;
27082   centroidPoint$1(x0$3 = x, y0$3 = y);
27083 }
27084
27085 function PathContext(context) {
27086   this._context = context;
27087 }
27088
27089 PathContext.prototype = {
27090   _radius: 4.5,
27091   pointRadius: function(_) {
27092     return this._radius = _, this;
27093   },
27094   polygonStart: function() {
27095     this._line = 0;
27096   },
27097   polygonEnd: function() {
27098     this._line = NaN;
27099   },
27100   lineStart: function() {
27101     this._point = 0;
27102   },
27103   lineEnd: function() {
27104     if (this._line === 0) this._context.closePath();
27105     this._point = NaN;
27106   },
27107   point: function(x, y) {
27108     switch (this._point) {
27109       case 0: {
27110         this._context.moveTo(x, y);
27111         this._point = 1;
27112         break;
27113       }
27114       case 1: {
27115         this._context.lineTo(x, y);
27116         break;
27117       }
27118       default: {
27119         this._context.moveTo(x + this._radius, y);
27120         this._context.arc(x, y, this._radius, 0, tau$3);
27121         break;
27122       }
27123     }
27124   },
27125   result: noop$1
27126 };
27127
27128 function PathString() {
27129   this._string = [];
27130 }
27131
27132 PathString.prototype = {
27133   _circle: circle$1(4.5),
27134   pointRadius: function(_) {
27135     return this._circle = circle$1(_), this;
27136   },
27137   polygonStart: function() {
27138     this._line = 0;
27139   },
27140   polygonEnd: function() {
27141     this._line = NaN;
27142   },
27143   lineStart: function() {
27144     this._point = 0;
27145   },
27146   lineEnd: function() {
27147     if (this._line === 0) this._string.push("Z");
27148     this._point = NaN;
27149   },
27150   point: function(x, y) {
27151     switch (this._point) {
27152       case 0: {
27153         this._string.push("M", x, ",", y);
27154         this._point = 1;
27155         break;
27156       }
27157       case 1: {
27158         this._string.push("L", x, ",", y);
27159         break;
27160       }
27161       default: {
27162         this._string.push("M", x, ",", y, this._circle);
27163         break;
27164       }
27165     }
27166   },
27167   result: function() {
27168     if (this._string.length) {
27169       var result = this._string.join("");
27170       this._string = [];
27171       return result;
27172     }
27173   }
27174 };
27175
27176 function circle$1(radius) {
27177   return "m0," + radius
27178       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
27179       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
27180       + "z";
27181 }
27182
27183 var index$4 = function(projection, context) {
27184   var pointRadius = 4.5,
27185       projectionStream,
27186       contextStream;
27187
27188   function path(object) {
27189     if (object) {
27190       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
27191       geoStream(object, projectionStream(contextStream));
27192     }
27193     return contextStream.result();
27194   }
27195
27196   path.area = function(object) {
27197     geoStream(object, projectionStream(areaStream$1));
27198     return areaStream$1.result();
27199   };
27200
27201   path.bounds = function(object) {
27202     geoStream(object, projectionStream(boundsStream$1));
27203     return boundsStream$1.result();
27204   };
27205
27206   path.centroid = function(object) {
27207     geoStream(object, projectionStream(centroidStream$1));
27208     return centroidStream$1.result();
27209   };
27210
27211   path.projection = function(_) {
27212     return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
27213   };
27214
27215   path.context = function(_) {
27216     if (!arguments.length) return context;
27217     contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _);
27218     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
27219     return path;
27220   };
27221
27222   path.pointRadius = function(_) {
27223     if (!arguments.length) return pointRadius;
27224     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
27225     return path;
27226   };
27227
27228   return path.projection(projection).context(context);
27229 };
27230
27231 var sum$1 = adder();
27232
27233 var polygonContains = function(polygon, point) {
27234   var lambda = point[0],
27235       phi = point[1],
27236       normal = [sin$1(lambda), -cos$1(lambda), 0],
27237       angle = 0,
27238       winding = 0;
27239
27240   sum$1.reset();
27241
27242   for (var i = 0, n = polygon.length; i < n; ++i) {
27243     if (!(m = (ring = polygon[i]).length)) continue;
27244     var ring,
27245         m,
27246         point0 = ring[m - 1],
27247         lambda0 = point0[0],
27248         phi0 = point0[1] / 2 + quarterPi,
27249         sinPhi0 = sin$1(phi0),
27250         cosPhi0 = cos$1(phi0);
27251
27252     for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
27253       var point1 = ring[j],
27254           lambda1 = point1[0],
27255           phi1 = point1[1] / 2 + quarterPi,
27256           sinPhi1 = sin$1(phi1),
27257           cosPhi1 = cos$1(phi1),
27258           delta = lambda1 - lambda0,
27259           sign$$1 = delta >= 0 ? 1 : -1,
27260           absDelta = sign$$1 * delta,
27261           antimeridian = absDelta > pi$3,
27262           k = sinPhi0 * sinPhi1;
27263
27264       sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
27265       angle += antimeridian ? delta + sign$$1 * tau$3 : delta;
27266
27267       // Are the longitudes either side of the point’s meridian (lambda),
27268       // and are the latitudes smaller than the parallel (phi)?
27269       if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
27270         var arc = cartesianCross(cartesian(point0), cartesian(point1));
27271         cartesianNormalizeInPlace(arc);
27272         var intersection = cartesianCross(normal, arc);
27273         cartesianNormalizeInPlace(intersection);
27274         var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
27275         if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
27276           winding += antimeridian ^ delta >= 0 ? 1 : -1;
27277         }
27278       }
27279     }
27280   }
27281
27282   // First, determine whether the South pole is inside or outside:
27283   //
27284   // It is inside if:
27285   // * the polygon winds around it in a clockwise direction.
27286   // * the polygon does not (cumulatively) wind around it, but has a negative
27287   //   (counter-clockwise) area.
27288   //
27289   // Second, count the (signed) number of times a segment crosses a lambda
27290   // from the point to the South pole.  If it is zero, then the point is the
27291   // same side as the South pole.
27292
27293   return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1);
27294 };
27295
27296 var clip = function(pointVisible, clipLine, interpolate, start) {
27297   return function(rotate, sink) {
27298     var line = clipLine(sink),
27299         rotatedStart = rotate.invert(start[0], start[1]),
27300         ringBuffer = clipBuffer(),
27301         ringSink = clipLine(ringBuffer),
27302         polygonStarted = false,
27303         polygon,
27304         segments,
27305         ring;
27306
27307     var clip = {
27308       point: point,
27309       lineStart: lineStart,
27310       lineEnd: lineEnd,
27311       polygonStart: function() {
27312         clip.point = pointRing;
27313         clip.lineStart = ringStart;
27314         clip.lineEnd = ringEnd;
27315         segments = [];
27316         polygon = [];
27317       },
27318       polygonEnd: function() {
27319         clip.point = point;
27320         clip.lineStart = lineStart;
27321         clip.lineEnd = lineEnd;
27322         segments = merge(segments);
27323         var startInside = polygonContains(polygon, rotatedStart);
27324         if (segments.length) {
27325           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27326           clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
27327         } else if (startInside) {
27328           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27329           sink.lineStart();
27330           interpolate(null, null, 1, sink);
27331           sink.lineEnd();
27332         }
27333         if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
27334         segments = polygon = null;
27335       },
27336       sphere: function() {
27337         sink.polygonStart();
27338         sink.lineStart();
27339         interpolate(null, null, 1, sink);
27340         sink.lineEnd();
27341         sink.polygonEnd();
27342       }
27343     };
27344
27345     function point(lambda, phi) {
27346       var point = rotate(lambda, phi);
27347       if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
27348     }
27349
27350     function pointLine(lambda, phi) {
27351       var point = rotate(lambda, phi);
27352       line.point(point[0], point[1]);
27353     }
27354
27355     function lineStart() {
27356       clip.point = pointLine;
27357       line.lineStart();
27358     }
27359
27360     function lineEnd() {
27361       clip.point = point;
27362       line.lineEnd();
27363     }
27364
27365     function pointRing(lambda, phi) {
27366       ring.push([lambda, phi]);
27367       var point = rotate(lambda, phi);
27368       ringSink.point(point[0], point[1]);
27369     }
27370
27371     function ringStart() {
27372       ringSink.lineStart();
27373       ring = [];
27374     }
27375
27376     function ringEnd() {
27377       pointRing(ring[0][0], ring[0][1]);
27378       ringSink.lineEnd();
27379
27380       var clean = ringSink.clean(),
27381           ringSegments = ringBuffer.result(),
27382           i, n = ringSegments.length, m,
27383           segment,
27384           point;
27385
27386       ring.pop();
27387       polygon.push(ring);
27388       ring = null;
27389
27390       if (!n) return;
27391
27392       // No intersections.
27393       if (clean & 1) {
27394         segment = ringSegments[0];
27395         if ((m = segment.length - 1) > 0) {
27396           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
27397           sink.lineStart();
27398           for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
27399           sink.lineEnd();
27400         }
27401         return;
27402       }
27403
27404       // Rejoin connected segments.
27405       // TODO reuse ringBuffer.rejoin()?
27406       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
27407
27408       segments.push(ringSegments.filter(validSegment));
27409     }
27410
27411     return clip;
27412   };
27413 };
27414
27415 function validSegment(segment) {
27416   return segment.length > 1;
27417 }
27418
27419 // Intersections are sorted along the clip edge. For both antimeridian cutting
27420 // and circle clipping, the same comparison is used.
27421 function compareIntersection(a, b) {
27422   return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1])
27423        - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]);
27424 }
27425
27426 var clipAntimeridian = clip(
27427   function() { return true; },
27428   clipAntimeridianLine,
27429   clipAntimeridianInterpolate,
27430   [-pi$3, -halfPi$2]
27431 );
27432
27433 // Takes a line and cuts into visible segments. Return values: 0 - there were
27434 // intersections or the line was empty; 1 - no intersections; 2 - there were
27435 // intersections, and the first and last segments should be rejoined.
27436 function clipAntimeridianLine(stream) {
27437   var lambda0 = NaN,
27438       phi0 = NaN,
27439       sign0 = NaN,
27440       clean; // no intersections
27441
27442   return {
27443     lineStart: function() {
27444       stream.lineStart();
27445       clean = 1;
27446     },
27447     point: function(lambda1, phi1) {
27448       var sign1 = lambda1 > 0 ? pi$3 : -pi$3,
27449           delta = abs(lambda1 - lambda0);
27450       if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole
27451         stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2);
27452         stream.point(sign0, phi0);
27453         stream.lineEnd();
27454         stream.lineStart();
27455         stream.point(sign1, phi0);
27456         stream.point(lambda1, phi0);
27457         clean = 0;
27458       } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian
27459         if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies
27460         if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2;
27461         phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
27462         stream.point(sign0, phi0);
27463         stream.lineEnd();
27464         stream.lineStart();
27465         stream.point(sign1, phi0);
27466         clean = 0;
27467       }
27468       stream.point(lambda0 = lambda1, phi0 = phi1);
27469       sign0 = sign1;
27470     },
27471     lineEnd: function() {
27472       stream.lineEnd();
27473       lambda0 = phi0 = NaN;
27474     },
27475     clean: function() {
27476       return 2 - clean; // if intersections, rejoin first and last segments
27477     }
27478   };
27479 }
27480
27481 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
27482   var cosPhi0,
27483       cosPhi1,
27484       sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
27485   return abs(sinLambda0Lambda1) > epsilon$2
27486       ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
27487           - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
27488           / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
27489       : (phi0 + phi1) / 2;
27490 }
27491
27492 function clipAntimeridianInterpolate(from, to, direction, stream) {
27493   var phi;
27494   if (from == null) {
27495     phi = direction * halfPi$2;
27496     stream.point(-pi$3, phi);
27497     stream.point(0, phi);
27498     stream.point(pi$3, phi);
27499     stream.point(pi$3, 0);
27500     stream.point(pi$3, -phi);
27501     stream.point(0, -phi);
27502     stream.point(-pi$3, -phi);
27503     stream.point(-pi$3, 0);
27504     stream.point(-pi$3, phi);
27505   } else if (abs(from[0] - to[0]) > epsilon$2) {
27506     var lambda = from[0] < to[0] ? pi$3 : -pi$3;
27507     phi = direction * lambda / 2;
27508     stream.point(-lambda, phi);
27509     stream.point(0, phi);
27510     stream.point(lambda, phi);
27511   } else {
27512     stream.point(to[0], to[1]);
27513   }
27514 }
27515
27516 var clipCircle = function(radius, delta) {
27517   var cr = cos$1(radius),
27518       smallRadius = cr > 0,
27519       notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case
27520
27521   function interpolate(from, to, direction, stream) {
27522     circleStream(stream, radius, delta, direction, from, to);
27523   }
27524
27525   function visible(lambda, phi) {
27526     return cos$1(lambda) * cos$1(phi) > cr;
27527   }
27528
27529   // Takes a line and cuts into visible segments. Return values used for polygon
27530   // clipping: 0 - there were intersections or the line was empty; 1 - no
27531   // intersections 2 - there were intersections, and the first and last segments
27532   // should be rejoined.
27533   function clipLine(stream) {
27534     var point0, // previous point
27535         c0, // code for previous point
27536         v0, // visibility of previous point
27537         v00, // visibility of first point
27538         clean; // no intersections
27539     return {
27540       lineStart: function() {
27541         v00 = v0 = false;
27542         clean = 1;
27543       },
27544       point: function(lambda, phi) {
27545         var point1 = [lambda, phi],
27546             point2,
27547             v = visible(lambda, phi),
27548             c = smallRadius
27549               ? v ? 0 : code(lambda, phi)
27550               : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0;
27551         if (!point0 && (v00 = v0 = v)) stream.lineStart();
27552         // Handle degeneracies.
27553         // TODO ignore if not clipping polygons.
27554         if (v !== v0) {
27555           point2 = intersect(point0, point1);
27556           if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
27557             point1[0] += epsilon$2;
27558             point1[1] += epsilon$2;
27559             v = visible(point1[0], point1[1]);
27560           }
27561         }
27562         if (v !== v0) {
27563           clean = 0;
27564           if (v) {
27565             // outside going in
27566             stream.lineStart();
27567             point2 = intersect(point1, point0);
27568             stream.point(point2[0], point2[1]);
27569           } else {
27570             // inside going out
27571             point2 = intersect(point0, point1);
27572             stream.point(point2[0], point2[1]);
27573             stream.lineEnd();
27574           }
27575           point0 = point2;
27576         } else if (notHemisphere && point0 && smallRadius ^ v) {
27577           var t;
27578           // If the codes for two points are different, or are both zero,
27579           // and there this segment intersects with the small circle.
27580           if (!(c & c0) && (t = intersect(point1, point0, true))) {
27581             clean = 0;
27582             if (smallRadius) {
27583               stream.lineStart();
27584               stream.point(t[0][0], t[0][1]);
27585               stream.point(t[1][0], t[1][1]);
27586               stream.lineEnd();
27587             } else {
27588               stream.point(t[1][0], t[1][1]);
27589               stream.lineEnd();
27590               stream.lineStart();
27591               stream.point(t[0][0], t[0][1]);
27592             }
27593           }
27594         }
27595         if (v && (!point0 || !pointEqual(point0, point1))) {
27596           stream.point(point1[0], point1[1]);
27597         }
27598         point0 = point1, v0 = v, c0 = c;
27599       },
27600       lineEnd: function() {
27601         if (v0) stream.lineEnd();
27602         point0 = null;
27603       },
27604       // Rejoin first and last segments if there were intersections and the first
27605       // and last points were visible.
27606       clean: function() {
27607         return clean | ((v00 && v0) << 1);
27608       }
27609     };
27610   }
27611
27612   // Intersects the great circle between a and b with the clip circle.
27613   function intersect(a, b, two) {
27614     var pa = cartesian(a),
27615         pb = cartesian(b);
27616
27617     // We have two planes, n1.p = d1 and n2.p = d2.
27618     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
27619     var n1 = [1, 0, 0], // normal
27620         n2 = cartesianCross(pa, pb),
27621         n2n2 = cartesianDot(n2, n2),
27622         n1n2 = n2[0], // cartesianDot(n1, n2),
27623         determinant = n2n2 - n1n2 * n1n2;
27624
27625     // Two polar points.
27626     if (!determinant) return !two && a;
27627
27628     var c1 =  cr * n2n2 / determinant,
27629         c2 = -cr * n1n2 / determinant,
27630         n1xn2 = cartesianCross(n1, n2),
27631         A = cartesianScale(n1, c1),
27632         B = cartesianScale(n2, c2);
27633     cartesianAddInPlace(A, B);
27634
27635     // Solve |p(t)|^2 = 1.
27636     var u = n1xn2,
27637         w = cartesianDot(A, u),
27638         uu = cartesianDot(u, u),
27639         t2 = w * w - uu * (cartesianDot(A, A) - 1);
27640
27641     if (t2 < 0) return;
27642
27643     var t = sqrt(t2),
27644         q = cartesianScale(u, (-w - t) / uu);
27645     cartesianAddInPlace(q, A);
27646     q = spherical(q);
27647
27648     if (!two) return q;
27649
27650     // Two intersection points.
27651     var lambda0 = a[0],
27652         lambda1 = b[0],
27653         phi0 = a[1],
27654         phi1 = b[1],
27655         z;
27656
27657     if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
27658
27659     var delta = lambda1 - lambda0,
27660         polar = abs(delta - pi$3) < epsilon$2,
27661         meridian = polar || delta < epsilon$2;
27662
27663     if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
27664
27665     // Check that the first point is between a and b.
27666     if (meridian
27667         ? polar
27668           ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1)
27669           : phi0 <= q[1] && q[1] <= phi1
27670         : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
27671       var q1 = cartesianScale(u, (-w + t) / uu);
27672       cartesianAddInPlace(q1, A);
27673       return [q, spherical(q1)];
27674     }
27675   }
27676
27677   // Generates a 4-bit vector representing the location of a point relative to
27678   // the small circle's bounding box.
27679   function code(lambda, phi) {
27680     var r = smallRadius ? radius : pi$3 - radius,
27681         code = 0;
27682     if (lambda < -r) code |= 1; // left
27683     else if (lambda > r) code |= 2; // right
27684     if (phi < -r) code |= 4; // below
27685     else if (phi > r) code |= 8; // above
27686     return code;
27687   }
27688
27689   return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]);
27690 };
27691
27692 var transform = function(methods) {
27693   return {
27694     stream: transformer(methods)
27695   };
27696 };
27697
27698 function transformer(methods) {
27699   return function(stream) {
27700     var s = new TransformStream;
27701     for (var key in methods) s[key] = methods[key];
27702     s.stream = stream;
27703     return s;
27704   };
27705 }
27706
27707 function TransformStream() {}
27708
27709 TransformStream.prototype = {
27710   constructor: TransformStream,
27711   point: function(x, y) { this.stream.point(x, y); },
27712   sphere: function() { this.stream.sphere(); },
27713   lineStart: function() { this.stream.lineStart(); },
27714   lineEnd: function() { this.stream.lineEnd(); },
27715   polygonStart: function() { this.stream.polygonStart(); },
27716   polygonEnd: function() { this.stream.polygonEnd(); }
27717 };
27718
27719 function fitExtent(projection, extent, object) {
27720   var w = extent[1][0] - extent[0][0],
27721       h = extent[1][1] - extent[0][1],
27722       clip = projection.clipExtent && projection.clipExtent();
27723
27724   projection
27725       .scale(150)
27726       .translate([0, 0]);
27727
27728   if (clip != null) projection.clipExtent(null);
27729
27730   geoStream(object, projection.stream(boundsStream$1));
27731
27732   var b = boundsStream$1.result(),
27733       k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
27734       x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
27735       y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
27736
27737   if (clip != null) projection.clipExtent(clip);
27738
27739   return projection
27740       .scale(k * 150)
27741       .translate([x, y]);
27742 }
27743
27744 function fitSize(projection, size, object) {
27745   return fitExtent(projection, [[0, 0], size], object);
27746 }
27747
27748 var maxDepth = 16;
27749 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
27750
27751 var resample = function(project, delta2) {
27752   return +delta2 ? resample$1(project, delta2) : resampleNone(project);
27753 };
27754
27755 function resampleNone(project) {
27756   return transformer({
27757     point: function(x, y) {
27758       x = project(x, y);
27759       this.stream.point(x[0], x[1]);
27760     }
27761   });
27762 }
27763
27764 function resample$1(project, delta2) {
27765
27766   function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
27767     var dx = x1 - x0,
27768         dy = y1 - y0,
27769         d2 = dx * dx + dy * dy;
27770     if (d2 > 4 * delta2 && depth--) {
27771       var a = a0 + a1,
27772           b = b0 + b1,
27773           c = c0 + c1,
27774           m = sqrt(a * a + b * b + c * c),
27775           phi2 = asin(c /= m),
27776           lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a),
27777           p = project(lambda2, phi2),
27778           x2 = p[0],
27779           y2 = p[1],
27780           dx2 = x2 - x0,
27781           dy2 = y2 - y0,
27782           dz = dy * dx2 - dx * dy2;
27783       if (dz * dz / d2 > delta2 // perpendicular projected distance
27784           || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
27785           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
27786         resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
27787         stream.point(x2, y2);
27788         resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
27789       }
27790     }
27791   }
27792   return function(stream) {
27793     var lambda00, x00, y00, a00, b00, c00, // first point
27794         lambda0, x0, y0, a0, b0, c0; // previous point
27795
27796     var resampleStream = {
27797       point: point,
27798       lineStart: lineStart,
27799       lineEnd: lineEnd,
27800       polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
27801       polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
27802     };
27803
27804     function point(x, y) {
27805       x = project(x, y);
27806       stream.point(x[0], x[1]);
27807     }
27808
27809     function lineStart() {
27810       x0 = NaN;
27811       resampleStream.point = linePoint;
27812       stream.lineStart();
27813     }
27814
27815     function linePoint(lambda, phi) {
27816       var c = cartesian([lambda, phi]), p = project(lambda, phi);
27817       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);
27818       stream.point(x0, y0);
27819     }
27820
27821     function lineEnd() {
27822       resampleStream.point = point;
27823       stream.lineEnd();
27824     }
27825
27826     function ringStart() {
27827       lineStart();
27828       resampleStream.point = ringPoint;
27829       resampleStream.lineEnd = ringEnd;
27830     }
27831
27832     function ringPoint(lambda, phi) {
27833       linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
27834       resampleStream.point = linePoint;
27835     }
27836
27837     function ringEnd() {
27838       resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
27839       resampleStream.lineEnd = lineEnd;
27840       lineEnd();
27841     }
27842
27843     return resampleStream;
27844   };
27845 }
27846
27847 var transformRadians = transformer({
27848   point: function(x, y) {
27849     this.stream.point(x * radians, y * radians);
27850   }
27851 });
27852
27853 function projection(project) {
27854   return projectionMutator(function() { return project; })();
27855 }
27856
27857 function projectionMutator(projectAt) {
27858   var project,
27859       k = 150, // scale
27860       x = 480, y = 250, // translate
27861       dx, dy, lambda = 0, phi = 0, // center
27862       deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
27863       theta = null, preclip = clipAntimeridian, // clip angle
27864       x0 = null, y0, x1, y1, postclip = identity$4, // clip extent
27865       delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
27866       cache,
27867       cacheStream;
27868
27869   function projection(point) {
27870     point = projectRotate(point[0] * radians, point[1] * radians);
27871     return [point[0] * k + dx, dy - point[1] * k];
27872   }
27873
27874   function invert(point) {
27875     point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
27876     return point && [point[0] * degrees$1, point[1] * degrees$1];
27877   }
27878
27879   function projectTransform(x, y) {
27880     return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
27881   }
27882
27883   projection.stream = function(stream) {
27884     return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
27885   };
27886
27887   projection.clipAngle = function(_) {
27888     return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
27889   };
27890
27891   projection.clipExtent = function(_) {
27892     return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
27893   };
27894
27895   projection.scale = function(_) {
27896     return arguments.length ? (k = +_, recenter()) : k;
27897   };
27898
27899   projection.translate = function(_) {
27900     return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
27901   };
27902
27903   projection.center = function(_) {
27904     return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
27905   };
27906
27907   projection.rotate = function(_) {
27908     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];
27909   };
27910
27911   projection.precision = function(_) {
27912     return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
27913   };
27914
27915   projection.fitExtent = function(extent, object) {
27916     return fitExtent(projection, extent, object);
27917   };
27918
27919   projection.fitSize = function(size, object) {
27920     return fitSize(projection, size, object);
27921   };
27922
27923   function recenter() {
27924     projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
27925     var center = project(lambda, phi);
27926     dx = x - center[0] * k;
27927     dy = y + center[1] * k;
27928     return reset();
27929   }
27930
27931   function reset() {
27932     cache = cacheStream = null;
27933     return projection;
27934   }
27935
27936   return function() {
27937     project = projectAt.apply(this, arguments);
27938     projection.invert = project.invert && invert;
27939     return recenter();
27940   };
27941 }
27942
27943 function conicProjection(projectAt) {
27944   var phi0 = 0,
27945       phi1 = pi$3 / 3,
27946       m = projectionMutator(projectAt),
27947       p = m(phi0, phi1);
27948
27949   p.parallels = function(_) {
27950     return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
27951   };
27952
27953   return p;
27954 }
27955
27956 function cylindricalEqualAreaRaw(phi0) {
27957   var cosPhi0 = cos$1(phi0);
27958
27959   function forward(lambda, phi) {
27960     return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
27961   }
27962
27963   forward.invert = function(x, y) {
27964     return [x / cosPhi0, asin(y * cosPhi0)];
27965   };
27966
27967   return forward;
27968 }
27969
27970 function conicEqualAreaRaw(y0, y1) {
27971   var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
27972
27973   // Are the parallels symmetrical around the Equator?
27974   if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0);
27975
27976   var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n;
27977
27978   function project(x, y) {
27979     var r = sqrt(c - 2 * n * sin$1(y)) / n;
27980     return [r * sin$1(x *= n), r0 - r * cos$1(x)];
27981   }
27982
27983   project.invert = function(x, y) {
27984     var r0y = r0 - y;
27985     return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
27986   };
27987
27988   return project;
27989 }
27990
27991 var conicEqualArea = function() {
27992   return conicProjection(conicEqualAreaRaw)
27993       .scale(155.424)
27994       .center([0, 33.6442]);
27995 };
27996
27997 var albers = function() {
27998   return conicEqualArea()
27999       .parallels([29.5, 45.5])
28000       .scale(1070)
28001       .translate([480, 250])
28002       .rotate([96, 0])
28003       .center([-0.6, 38.7]);
28004 };
28005
28006 // The projections must have mutually exclusive clip regions on the sphere,
28007 // as this will avoid emitting interleaving lines and polygons.
28008 function multiplex(streams) {
28009   var n = streams.length;
28010   return {
28011     point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
28012     sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
28013     lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
28014     lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
28015     polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
28016     polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
28017   };
28018 }
28019
28020 // A composite projection for the United States, configured by default for
28021 // 960×500. The projection also works quite well at 960×600 if you change the
28022 // scale to 1285 and adjust the translate accordingly. The set of standard
28023 // parallels for each region comes from USGS, which is published here:
28024 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
28025 var albersUsa = function() {
28026   var cache,
28027       cacheStream,
28028       lower48 = albers(), lower48Point,
28029       alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
28030       hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
28031       point, pointStream = {point: function(x, y) { point = [x, y]; }};
28032
28033   function albersUsa(coordinates) {
28034     var x = coordinates[0], y = coordinates[1];
28035     return point = null,
28036         (lower48Point.point(x, y), point)
28037         || (alaskaPoint.point(x, y), point)
28038         || (hawaiiPoint.point(x, y), point);
28039   }
28040
28041   albersUsa.invert = function(coordinates) {
28042     var k = lower48.scale(),
28043         t = lower48.translate(),
28044         x = (coordinates[0] - t[0]) / k,
28045         y = (coordinates[1] - t[1]) / k;
28046     return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
28047         : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
28048         : lower48).invert(coordinates);
28049   };
28050
28051   albersUsa.stream = function(stream) {
28052     return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
28053   };
28054
28055   albersUsa.precision = function(_) {
28056     if (!arguments.length) return lower48.precision();
28057     lower48.precision(_), alaska.precision(_), hawaii.precision(_);
28058     return reset();
28059   };
28060
28061   albersUsa.scale = function(_) {
28062     if (!arguments.length) return lower48.scale();
28063     lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
28064     return albersUsa.translate(lower48.translate());
28065   };
28066
28067   albersUsa.translate = function(_) {
28068     if (!arguments.length) return lower48.translate();
28069     var k = lower48.scale(), x = +_[0], y = +_[1];
28070
28071     lower48Point = lower48
28072         .translate(_)
28073         .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
28074         .stream(pointStream);
28075
28076     alaskaPoint = alaska
28077         .translate([x - 0.307 * k, y + 0.201 * k])
28078         .clipExtent([[x - 0.425 * k + epsilon$2, y + 0.120 * k + epsilon$2], [x - 0.214 * k - epsilon$2, y + 0.234 * k - epsilon$2]])
28079         .stream(pointStream);
28080
28081     hawaiiPoint = hawaii
28082         .translate([x - 0.205 * k, y + 0.212 * k])
28083         .clipExtent([[x - 0.214 * k + epsilon$2, y + 0.166 * k + epsilon$2], [x - 0.115 * k - epsilon$2, y + 0.234 * k - epsilon$2]])
28084         .stream(pointStream);
28085
28086     return reset();
28087   };
28088
28089   albersUsa.fitExtent = function(extent, object) {
28090     return fitExtent(albersUsa, extent, object);
28091   };
28092
28093   albersUsa.fitSize = function(size, object) {
28094     return fitSize(albersUsa, size, object);
28095   };
28096
28097   function reset() {
28098     cache = cacheStream = null;
28099     return albersUsa;
28100   }
28101
28102   return albersUsa.scale(1070);
28103 };
28104
28105 function azimuthalRaw(scale) {
28106   return function(x, y) {
28107     var cx = cos$1(x),
28108         cy = cos$1(y),
28109         k = scale(cx * cy);
28110     return [
28111       k * cy * sin$1(x),
28112       k * sin$1(y)
28113     ];
28114   }
28115 }
28116
28117 function azimuthalInvert(angle) {
28118   return function(x, y) {
28119     var z = sqrt(x * x + y * y),
28120         c = angle(z),
28121         sc = sin$1(c),
28122         cc = cos$1(c);
28123     return [
28124       atan2(x * sc, z * cc),
28125       asin(z && y * sc / z)
28126     ];
28127   }
28128 }
28129
28130 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
28131   return sqrt(2 / (1 + cxcy));
28132 });
28133
28134 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
28135   return 2 * asin(z / 2);
28136 });
28137
28138 var azimuthalEqualArea = function() {
28139   return projection(azimuthalEqualAreaRaw)
28140       .scale(124.75)
28141       .clipAngle(180 - 1e-3);
28142 };
28143
28144 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
28145   return (c = acos(c)) && c / sin$1(c);
28146 });
28147
28148 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
28149   return z;
28150 });
28151
28152 var azimuthalEquidistant = function() {
28153   return projection(azimuthalEquidistantRaw)
28154       .scale(79.4188)
28155       .clipAngle(180 - 1e-3);
28156 };
28157
28158 function mercatorRaw(lambda, phi) {
28159   return [lambda, log(tan((halfPi$2 + phi) / 2))];
28160 }
28161
28162 mercatorRaw.invert = function(x, y) {
28163   return [x, 2 * atan(exp(y)) - halfPi$2];
28164 };
28165
28166 var mercator = function() {
28167   return mercatorProjection(mercatorRaw)
28168       .scale(961 / tau$3);
28169 };
28170
28171 function mercatorProjection(project) {
28172   var m = projection(project),
28173       scale = m.scale,
28174       translate = m.translate,
28175       clipExtent = m.clipExtent,
28176       clipAuto;
28177
28178   m.scale = function(_) {
28179     return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale();
28180   };
28181
28182   m.translate = function(_) {
28183     return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate();
28184   };
28185
28186   m.clipExtent = function(_) {
28187     if (!arguments.length) return clipAuto ? null : clipExtent();
28188     if (clipAuto = _ == null) {
28189       var k = pi$3 * scale(),
28190           t = translate();
28191       _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]];
28192     }
28193     clipExtent(_);
28194     return m;
28195   };
28196
28197   return m.clipExtent(null);
28198 }
28199
28200 function tany(y) {
28201   return tan((halfPi$2 + y) / 2);
28202 }
28203
28204 function conicConformalRaw(y0, y1) {
28205   var cy0 = cos$1(y0),
28206       n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)),
28207       f = cy0 * pow(tany(y0), n) / n;
28208
28209   if (!n) return mercatorRaw;
28210
28211   function project(x, y) {
28212     if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; }
28213     else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; }
28214     var r = f / pow(tany(y), n);
28215     return [r * sin$1(n * x), f - r * cos$1(n * x)];
28216   }
28217
28218   project.invert = function(x, y) {
28219     var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy);
28220     return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2];
28221   };
28222
28223   return project;
28224 }
28225
28226 var conicConformal = function() {
28227   return conicProjection(conicConformalRaw)
28228       .scale(109.5)
28229       .parallels([30, 30]);
28230 };
28231
28232 function equirectangularRaw(lambda, phi) {
28233   return [lambda, phi];
28234 }
28235
28236 equirectangularRaw.invert = equirectangularRaw;
28237
28238 var equirectangular = function() {
28239   return projection(equirectangularRaw)
28240       .scale(152.63);
28241 };
28242
28243 function conicEquidistantRaw(y0, y1) {
28244   var cy0 = cos$1(y0),
28245       n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
28246       g = cy0 / n + y0;
28247
28248   if (abs(n) < epsilon$2) return equirectangularRaw;
28249
28250   function project(x, y) {
28251     var gy = g - y, nx = n * x;
28252     return [gy * sin$1(nx), g - gy * cos$1(nx)];
28253   }
28254
28255   project.invert = function(x, y) {
28256     var gy = g - y;
28257     return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)];
28258   };
28259
28260   return project;
28261 }
28262
28263 var conicEquidistant = function() {
28264   return conicProjection(conicEquidistantRaw)
28265       .scale(131.154)
28266       .center([0, 13.9389]);
28267 };
28268
28269 function gnomonicRaw(x, y) {
28270   var cy = cos$1(y), k = cos$1(x) * cy;
28271   return [cy * sin$1(x) / k, sin$1(y) / k];
28272 }
28273
28274 gnomonicRaw.invert = azimuthalInvert(atan);
28275
28276 var gnomonic = function() {
28277   return projection(gnomonicRaw)
28278       .scale(144.049)
28279       .clipAngle(60);
28280 };
28281
28282 function scaleTranslate(kx, ky, tx, ty) {
28283   return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({
28284     point: function(x, y) {
28285       this.stream.point(x * kx + tx, y * ky + ty);
28286     }
28287   });
28288 }
28289
28290 var identity$5 = function() {
28291   var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$4, // scale, translate and reflect
28292       x0 = null, y0, x1, y1, clip = identity$4, // clip extent
28293       cache,
28294       cacheStream,
28295       projection;
28296
28297   function reset() {
28298     cache = cacheStream = null;
28299     return projection;
28300   }
28301
28302   return projection = {
28303     stream: function(stream) {
28304       return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
28305     },
28306     clipExtent: function(_) {
28307       return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
28308     },
28309     scale: function(_) {
28310       return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k;
28311     },
28312     translate: function(_) {
28313       return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
28314     },
28315     reflectX: function(_) {
28316       return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0;
28317     },
28318     reflectY: function(_) {
28319       return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0;
28320     },
28321     fitExtent: function(extent, object) {
28322       return fitExtent(projection, extent, object);
28323     },
28324     fitSize: function(size, object) {
28325       return fitSize(projection, size, object);
28326     }
28327   };
28328 };
28329
28330 function orthographicRaw(x, y) {
28331   return [cos$1(y) * sin$1(x), sin$1(y)];
28332 }
28333
28334 orthographicRaw.invert = azimuthalInvert(asin);
28335
28336 var orthographic = function() {
28337   return projection(orthographicRaw)
28338       .scale(249.5)
28339       .clipAngle(90 + epsilon$2);
28340 };
28341
28342 function stereographicRaw(x, y) {
28343   var cy = cos$1(y), k = 1 + cos$1(x) * cy;
28344   return [cy * sin$1(x) / k, sin$1(y) / k];
28345 }
28346
28347 stereographicRaw.invert = azimuthalInvert(function(z) {
28348   return 2 * atan(z);
28349 });
28350
28351 var stereographic = function() {
28352   return projection(stereographicRaw)
28353       .scale(250)
28354       .clipAngle(142);
28355 };
28356
28357 function transverseMercatorRaw(lambda, phi) {
28358   return [log(tan((halfPi$2 + phi) / 2)), -lambda];
28359 }
28360
28361 transverseMercatorRaw.invert = function(x, y) {
28362   return [-y, 2 * atan(exp(x)) - halfPi$2];
28363 };
28364
28365 var transverseMercator = function() {
28366   var m = mercatorProjection(transverseMercatorRaw),
28367       center = m.center,
28368       rotate = m.rotate;
28369
28370   m.center = function(_) {
28371     return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
28372   };
28373
28374   m.rotate = function(_) {
28375     return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
28376   };
28377
28378   return rotate([0, 0, 90])
28379       .scale(159.155);
28380 };
28381
28382 function defaultSeparation(a, b) {
28383   return a.parent === b.parent ? 1 : 2;
28384 }
28385
28386 function meanX(children) {
28387   return children.reduce(meanXReduce, 0) / children.length;
28388 }
28389
28390 function meanXReduce(x, c) {
28391   return x + c.x;
28392 }
28393
28394 function maxY(children) {
28395   return 1 + children.reduce(maxYReduce, 0);
28396 }
28397
28398 function maxYReduce(y, c) {
28399   return Math.max(y, c.y);
28400 }
28401
28402 function leafLeft(node) {
28403   var children;
28404   while (children = node.children) node = children[0];
28405   return node;
28406 }
28407
28408 function leafRight(node) {
28409   var children;
28410   while (children = node.children) node = children[children.length - 1];
28411   return node;
28412 }
28413
28414 var cluster = function() {
28415   var separation = defaultSeparation,
28416       dx = 1,
28417       dy = 1,
28418       nodeSize = false;
28419
28420   function cluster(root) {
28421     var previousNode,
28422         x = 0;
28423
28424     // First walk, computing the initial x & y values.
28425     root.eachAfter(function(node) {
28426       var children = node.children;
28427       if (children) {
28428         node.x = meanX(children);
28429         node.y = maxY(children);
28430       } else {
28431         node.x = previousNode ? x += separation(node, previousNode) : 0;
28432         node.y = 0;
28433         previousNode = node;
28434       }
28435     });
28436
28437     var left = leafLeft(root),
28438         right = leafRight(root),
28439         x0 = left.x - separation(left, right) / 2,
28440         x1 = right.x + separation(right, left) / 2;
28441
28442     // Second walk, normalizing x & y to the desired size.
28443     return root.eachAfter(nodeSize ? function(node) {
28444       node.x = (node.x - root.x) * dx;
28445       node.y = (root.y - node.y) * dy;
28446     } : function(node) {
28447       node.x = (node.x - x0) / (x1 - x0) * dx;
28448       node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28449     });
28450   }
28451
28452   cluster.separation = function(x) {
28453     return arguments.length ? (separation = x, cluster) : separation;
28454   };
28455
28456   cluster.size = function(x) {
28457     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28458   };
28459
28460   cluster.nodeSize = function(x) {
28461     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28462   };
28463
28464   return cluster;
28465 };
28466
28467 function count(node) {
28468   var sum = 0,
28469       children = node.children,
28470       i = children && children.length;
28471   if (!i) sum = 1;
28472   else while (--i >= 0) sum += children[i].value;
28473   node.value = sum;
28474 }
28475
28476 var node_count = function() {
28477   return this.eachAfter(count);
28478 };
28479
28480 var node_each = function(callback) {
28481   var node = this, current, next = [node], children, i, n;
28482   do {
28483     current = next.reverse(), next = [];
28484     while (node = current.pop()) {
28485       callback(node), children = node.children;
28486       if (children) for (i = 0, n = children.length; i < n; ++i) {
28487         next.push(children[i]);
28488       }
28489     }
28490   } while (next.length);
28491   return this;
28492 };
28493
28494 var node_eachBefore = function(callback) {
28495   var node = this, nodes = [node], children, i;
28496   while (node = nodes.pop()) {
28497     callback(node), children = node.children;
28498     if (children) for (i = children.length - 1; i >= 0; --i) {
28499       nodes.push(children[i]);
28500     }
28501   }
28502   return this;
28503 };
28504
28505 var node_eachAfter = function(callback) {
28506   var node = this, nodes = [node], next = [], children, i, n;
28507   while (node = nodes.pop()) {
28508     next.push(node), children = node.children;
28509     if (children) for (i = 0, n = children.length; i < n; ++i) {
28510       nodes.push(children[i]);
28511     }
28512   }
28513   while (node = next.pop()) {
28514     callback(node);
28515   }
28516   return this;
28517 };
28518
28519 var node_sum = function(value) {
28520   return this.eachAfter(function(node) {
28521     var sum = +value(node.data) || 0,
28522         children = node.children,
28523         i = children && children.length;
28524     while (--i >= 0) sum += children[i].value;
28525     node.value = sum;
28526   });
28527 };
28528
28529 var node_sort = function(compare) {
28530   return this.eachBefore(function(node) {
28531     if (node.children) {
28532       node.children.sort(compare);
28533     }
28534   });
28535 };
28536
28537 var node_path = function(end) {
28538   var start = this,
28539       ancestor = leastCommonAncestor(start, end),
28540       nodes = [start];
28541   while (start !== ancestor) {
28542     start = start.parent;
28543     nodes.push(start);
28544   }
28545   var k = nodes.length;
28546   while (end !== ancestor) {
28547     nodes.splice(k, 0, end);
28548     end = end.parent;
28549   }
28550   return nodes;
28551 };
28552
28553 function leastCommonAncestor(a, b) {
28554   if (a === b) return a;
28555   var aNodes = a.ancestors(),
28556       bNodes = b.ancestors(),
28557       c = null;
28558   a = aNodes.pop();
28559   b = bNodes.pop();
28560   while (a === b) {
28561     c = a;
28562     a = aNodes.pop();
28563     b = bNodes.pop();
28564   }
28565   return c;
28566 }
28567
28568 var node_ancestors = function() {
28569   var node = this, nodes = [node];
28570   while (node = node.parent) {
28571     nodes.push(node);
28572   }
28573   return nodes;
28574 };
28575
28576 var node_descendants = function() {
28577   var nodes = [];
28578   this.each(function(node) {
28579     nodes.push(node);
28580   });
28581   return nodes;
28582 };
28583
28584 var node_leaves = function() {
28585   var leaves = [];
28586   this.eachBefore(function(node) {
28587     if (!node.children) {
28588       leaves.push(node);
28589     }
28590   });
28591   return leaves;
28592 };
28593
28594 var node_links = function() {
28595   var root = this, links = [];
28596   root.each(function(node) {
28597     if (node !== root) { // Don’t include the root’s parent, if any.
28598       links.push({source: node.parent, target: node});
28599     }
28600   });
28601   return links;
28602 };
28603
28604 function hierarchy(data, children) {
28605   var root = new Node(data),
28606       valued = +data.value && (root.value = data.value),
28607       node,
28608       nodes = [root],
28609       child,
28610       childs,
28611       i,
28612       n;
28613
28614   if (children == null) children = defaultChildren;
28615
28616   while (node = nodes.pop()) {
28617     if (valued) node.value = +node.data.value;
28618     if ((childs = children(node.data)) && (n = childs.length)) {
28619       node.children = new Array(n);
28620       for (i = n - 1; i >= 0; --i) {
28621         nodes.push(child = node.children[i] = new Node(childs[i]));
28622         child.parent = node;
28623         child.depth = node.depth + 1;
28624       }
28625     }
28626   }
28627
28628   return root.eachBefore(computeHeight);
28629 }
28630
28631 function node_copy() {
28632   return hierarchy(this).eachBefore(copyData);
28633 }
28634
28635 function defaultChildren(d) {
28636   return d.children;
28637 }
28638
28639 function copyData(node) {
28640   node.data = node.data.data;
28641 }
28642
28643 function computeHeight(node) {
28644   var height = 0;
28645   do node.height = height;
28646   while ((node = node.parent) && (node.height < ++height));
28647 }
28648
28649 function Node(data) {
28650   this.data = data;
28651   this.depth =
28652   this.height = 0;
28653   this.parent = null;
28654 }
28655
28656 Node.prototype = hierarchy.prototype = {
28657   constructor: Node,
28658   count: node_count,
28659   each: node_each,
28660   eachAfter: node_eachAfter,
28661   eachBefore: node_eachBefore,
28662   sum: node_sum,
28663   sort: node_sort,
28664   path: node_path,
28665   ancestors: node_ancestors,
28666   descendants: node_descendants,
28667   leaves: node_leaves,
28668   links: node_links,
28669   copy: node_copy
28670 };
28671
28672 function Node$2(value) {
28673   this._ = value;
28674   this.next = null;
28675 }
28676
28677 var shuffle$1 = function(array) {
28678   var i,
28679       n = (array = array.slice()).length,
28680       head = null,
28681       node = head;
28682
28683   while (n) {
28684     var next = new Node$2(array[n - 1]);
28685     if (node) node = node.next = next;
28686     else node = head = next;
28687     array[i] = array[--n];
28688   }
28689
28690   return {
28691     head: head,
28692     tail: node
28693   };
28694 };
28695
28696 var enclose = function(circles) {
28697   return encloseN(shuffle$1(circles), []);
28698 };
28699
28700 function encloses(a, b) {
28701   var dx = b.x - a.x,
28702       dy = b.y - a.y,
28703       dr = a.r - b.r;
28704   return dr * dr + 1e-6 > dx * dx + dy * dy;
28705 }
28706
28707 // Returns the smallest circle that contains circles L and intersects circles B.
28708 function encloseN(L, B) {
28709   var circle,
28710       l0 = null,
28711       l1 = L.head,
28712       l2,
28713       p1;
28714
28715   switch (B.length) {
28716     case 1: circle = enclose1(B[0]); break;
28717     case 2: circle = enclose2(B[0], B[1]); break;
28718     case 3: circle = enclose3(B[0], B[1], B[2]); break;
28719   }
28720
28721   while (l1) {
28722     p1 = l1._, l2 = l1.next;
28723     if (!circle || !encloses(circle, p1)) {
28724
28725       // Temporarily truncate L before l1.
28726       if (l0) L.tail = l0, l0.next = null;
28727       else L.head = L.tail = null;
28728
28729       B.push(p1);
28730       circle = encloseN(L, B); // Note: reorders L!
28731       B.pop();
28732
28733       // Move l1 to the front of L and reconnect the truncated list L.
28734       if (L.head) l1.next = L.head, L.head = l1;
28735       else l1.next = null, L.head = L.tail = l1;
28736       l0 = L.tail, l0.next = l2;
28737
28738     } else {
28739       l0 = l1;
28740     }
28741     l1 = l2;
28742   }
28743
28744   L.tail = l0;
28745   return circle;
28746 }
28747
28748 function enclose1(a) {
28749   return {
28750     x: a.x,
28751     y: a.y,
28752     r: a.r
28753   };
28754 }
28755
28756 function enclose2(a, b) {
28757   var x1 = a.x, y1 = a.y, r1 = a.r,
28758       x2 = b.x, y2 = b.y, r2 = b.r,
28759       x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
28760       l = Math.sqrt(x21 * x21 + y21 * y21);
28761   return {
28762     x: (x1 + x2 + x21 / l * r21) / 2,
28763     y: (y1 + y2 + y21 / l * r21) / 2,
28764     r: (l + r1 + r2) / 2
28765   };
28766 }
28767
28768 function enclose3(a, b, c) {
28769   var x1 = a.x, y1 = a.y, r1 = a.r,
28770       x2 = b.x, y2 = b.y, r2 = b.r,
28771       x3 = c.x, y3 = c.y, r3 = c.r,
28772       a2 = 2 * (x1 - x2),
28773       b2 = 2 * (y1 - y2),
28774       c2 = 2 * (r2 - r1),
28775       d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
28776       a3 = 2 * (x1 - x3),
28777       b3 = 2 * (y1 - y3),
28778       c3 = 2 * (r3 - r1),
28779       d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
28780       ab = a3 * b2 - a2 * b3,
28781       xa = (b2 * d3 - b3 * d2) / ab - x1,
28782       xb = (b3 * c2 - b2 * c3) / ab,
28783       ya = (a3 * d2 - a2 * d3) / ab - y1,
28784       yb = (a2 * c3 - a3 * c2) / ab,
28785       A = xb * xb + yb * yb - 1,
28786       B = 2 * (xa * xb + ya * yb + r1),
28787       C = xa * xa + ya * ya - r1 * r1,
28788       r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
28789   return {
28790     x: xa + xb * r + x1,
28791     y: ya + yb * r + y1,
28792     r: r
28793   };
28794 }
28795
28796 function place(a, b, c) {
28797   var ax = a.x,
28798       ay = a.y,
28799       da = b.r + c.r,
28800       db = a.r + c.r,
28801       dx = b.x - ax,
28802       dy = b.y - ay,
28803       dc = dx * dx + dy * dy;
28804   if (dc) {
28805     var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
28806         y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
28807     c.x = ax + x * dx + y * dy;
28808     c.y = ay + x * dy - y * dx;
28809   } else {
28810     c.x = ax + db;
28811     c.y = ay;
28812   }
28813 }
28814
28815 function intersects(a, b) {
28816   var dx = b.x - a.x,
28817       dy = b.y - a.y,
28818       dr = a.r + b.r;
28819   return dr * dr - 1e-6 > dx * dx + dy * dy;
28820 }
28821
28822 function distance1(a, b) {
28823   var l = a._.r;
28824   while (a !== b) l += 2 * (a = a.next)._.r;
28825   return l - b._.r;
28826 }
28827
28828 function distance2(circle, x, y) {
28829   var dx = circle.x - x,
28830       dy = circle.y - y;
28831   return dx * dx + dy * dy;
28832 }
28833
28834 function Node$1(circle) {
28835   this._ = circle;
28836   this.next = null;
28837   this.previous = null;
28838 }
28839
28840 function packEnclose(circles) {
28841   if (!(n = circles.length)) return 0;
28842
28843   var a, b, c, n;
28844
28845   // Place the first circle.
28846   a = circles[0], a.x = 0, a.y = 0;
28847   if (!(n > 1)) return a.r;
28848
28849   // Place the second circle.
28850   b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
28851   if (!(n > 2)) return a.r + b.r;
28852
28853   // Place the third circle.
28854   place(b, a, c = circles[2]);
28855
28856   // Initialize the weighted centroid.
28857   var aa = a.r * a.r,
28858       ba = b.r * b.r,
28859       ca = c.r * c.r,
28860       oa = aa + ba + ca,
28861       ox = aa * a.x + ba * b.x + ca * c.x,
28862       oy = aa * a.y + ba * b.y + ca * c.y,
28863       cx, cy, i, j, k, sj, sk;
28864
28865   // Initialize the front-chain using the first three circles a, b and c.
28866   a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
28867   a.next = c.previous = b;
28868   b.next = a.previous = c;
28869   c.next = b.previous = a;
28870
28871   // Attempt to place each remaining circle…
28872   pack: for (i = 3; i < n; ++i) {
28873     place(a._, b._, c = circles[i]), c = new Node$1(c);
28874
28875     // Find the closest intersecting circle on the front-chain, if any.
28876     // “Closeness” is determined by linear distance along the front-chain.
28877     // “Ahead” or “behind” is likewise determined by linear distance.
28878     j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
28879     do {
28880       if (sj <= sk) {
28881         if (intersects(j._, c._)) {
28882           if (sj + a._.r + b._.r > distance1(j, b)) a = j; else b = j;
28883           a.next = b, b.previous = a, --i;
28884           continue pack;
28885         }
28886         sj += j._.r, j = j.next;
28887       } else {
28888         if (intersects(k._, c._)) {
28889           if (distance1(a, k) > sk + a._.r + b._.r) a = k; else b = k;
28890           a.next = b, b.previous = a, --i;
28891           continue pack;
28892         }
28893         sk += k._.r, k = k.previous;
28894       }
28895     } while (j !== k.next);
28896
28897     // Success! Insert the new circle c between a and b.
28898     c.previous = a, c.next = b, a.next = b.previous = b = c;
28899
28900     // Update the weighted centroid.
28901     oa += ca = c._.r * c._.r;
28902     ox += ca * c._.x;
28903     oy += ca * c._.y;
28904
28905     // Compute the new closest circle a to centroid.
28906     aa = distance2(a._, cx = ox / oa, cy = oy / oa);
28907     while ((c = c.next) !== b) {
28908       if ((ca = distance2(c._, cx, cy)) < aa) {
28909         a = c, aa = ca;
28910       }
28911     }
28912     b = a.next;
28913   }
28914
28915   // Compute the enclosing circle of the front chain.
28916   a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
28917
28918   // Translate the circles to put the enclosing circle around the origin.
28919   for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
28920
28921   return c.r;
28922 }
28923
28924 var siblings = function(circles) {
28925   packEnclose(circles);
28926   return circles;
28927 };
28928
28929 function optional(f) {
28930   return f == null ? null : required(f);
28931 }
28932
28933 function required(f) {
28934   if (typeof f !== "function") throw new Error;
28935   return f;
28936 }
28937
28938 function constantZero() {
28939   return 0;
28940 }
28941
28942 var constant$8 = function(x) {
28943   return function() {
28944     return x;
28945   };
28946 };
28947
28948 function defaultRadius$1(d) {
28949   return Math.sqrt(d.value);
28950 }
28951
28952 var index$5 = function() {
28953   var radius = null,
28954       dx = 1,
28955       dy = 1,
28956       padding = constantZero;
28957
28958   function pack(root) {
28959     root.x = dx / 2, root.y = dy / 2;
28960     if (radius) {
28961       root.eachBefore(radiusLeaf(radius))
28962           .eachAfter(packChildren(padding, 0.5))
28963           .eachBefore(translateChild(1));
28964     } else {
28965       root.eachBefore(radiusLeaf(defaultRadius$1))
28966           .eachAfter(packChildren(constantZero, 1))
28967           .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
28968           .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
28969     }
28970     return root;
28971   }
28972
28973   pack.radius = function(x) {
28974     return arguments.length ? (radius = optional(x), pack) : radius;
28975   };
28976
28977   pack.size = function(x) {
28978     return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
28979   };
28980
28981   pack.padding = function(x) {
28982     return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding;
28983   };
28984
28985   return pack;
28986 };
28987
28988 function radiusLeaf(radius) {
28989   return function(node) {
28990     if (!node.children) {
28991       node.r = Math.max(0, +radius(node) || 0);
28992     }
28993   };
28994 }
28995
28996 function packChildren(padding, k) {
28997   return function(node) {
28998     if (children = node.children) {
28999       var children,
29000           i,
29001           n = children.length,
29002           r = padding(node) * k || 0,
29003           e;
29004
29005       if (r) for (i = 0; i < n; ++i) children[i].r += r;
29006       e = packEnclose(children);
29007       if (r) for (i = 0; i < n; ++i) children[i].r -= r;
29008       node.r = e + r;
29009     }
29010   };
29011 }
29012
29013 function translateChild(k) {
29014   return function(node) {
29015     var parent = node.parent;
29016     node.r *= k;
29017     if (parent) {
29018       node.x = parent.x + k * node.x;
29019       node.y = parent.y + k * node.y;
29020     }
29021   };
29022 }
29023
29024 var roundNode = function(node) {
29025   node.x0 = Math.round(node.x0);
29026   node.y0 = Math.round(node.y0);
29027   node.x1 = Math.round(node.x1);
29028   node.y1 = Math.round(node.y1);
29029 };
29030
29031 var treemapDice = function(parent, x0, y0, x1, y1) {
29032   var nodes = parent.children,
29033       node,
29034       i = -1,
29035       n = nodes.length,
29036       k = parent.value && (x1 - x0) / parent.value;
29037
29038   while (++i < n) {
29039     node = nodes[i], node.y0 = y0, node.y1 = y1;
29040     node.x0 = x0, node.x1 = x0 += node.value * k;
29041   }
29042 };
29043
29044 var partition = function() {
29045   var dx = 1,
29046       dy = 1,
29047       padding = 0,
29048       round = false;
29049
29050   function partition(root) {
29051     var n = root.height + 1;
29052     root.x0 =
29053     root.y0 = padding;
29054     root.x1 = dx;
29055     root.y1 = dy / n;
29056     root.eachBefore(positionNode(dy, n));
29057     if (round) root.eachBefore(roundNode);
29058     return root;
29059   }
29060
29061   function positionNode(dy, n) {
29062     return function(node) {
29063       if (node.children) {
29064         treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
29065       }
29066       var x0 = node.x0,
29067           y0 = node.y0,
29068           x1 = node.x1 - padding,
29069           y1 = node.y1 - padding;
29070       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29071       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29072       node.x0 = x0;
29073       node.y0 = y0;
29074       node.x1 = x1;
29075       node.y1 = y1;
29076     };
29077   }
29078
29079   partition.round = function(x) {
29080     return arguments.length ? (round = !!x, partition) : round;
29081   };
29082
29083   partition.size = function(x) {
29084     return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
29085   };
29086
29087   partition.padding = function(x) {
29088     return arguments.length ? (padding = +x, partition) : padding;
29089   };
29090
29091   return partition;
29092 };
29093
29094 var keyPrefix$1 = "$";
29095 var preroot = {depth: -1};
29096 var ambiguous = {};
29097
29098 function defaultId(d) {
29099   return d.id;
29100 }
29101
29102 function defaultParentId(d) {
29103   return d.parentId;
29104 }
29105
29106 var stratify = function() {
29107   var id = defaultId,
29108       parentId = defaultParentId;
29109
29110   function stratify(data) {
29111     var d,
29112         i,
29113         n = data.length,
29114         root,
29115         parent,
29116         node,
29117         nodes = new Array(n),
29118         nodeId,
29119         nodeKey,
29120         nodeByKey = {};
29121
29122     for (i = 0; i < n; ++i) {
29123       d = data[i], node = nodes[i] = new Node(d);
29124       if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29125         nodeKey = keyPrefix$1 + (node.id = nodeId);
29126         nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29127       }
29128     }
29129
29130     for (i = 0; i < n; ++i) {
29131       node = nodes[i], nodeId = parentId(data[i], i, data);
29132       if (nodeId == null || !(nodeId += "")) {
29133         if (root) throw new Error("multiple roots");
29134         root = node;
29135       } else {
29136         parent = nodeByKey[keyPrefix$1 + nodeId];
29137         if (!parent) throw new Error("missing: " + nodeId);
29138         if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29139         if (parent.children) parent.children.push(node);
29140         else parent.children = [node];
29141         node.parent = parent;
29142       }
29143     }
29144
29145     if (!root) throw new Error("no root");
29146     root.parent = preroot;
29147     root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29148     root.parent = null;
29149     if (n > 0) throw new Error("cycle");
29150
29151     return root;
29152   }
29153
29154   stratify.id = function(x) {
29155     return arguments.length ? (id = required(x), stratify) : id;
29156   };
29157
29158   stratify.parentId = function(x) {
29159     return arguments.length ? (parentId = required(x), stratify) : parentId;
29160   };
29161
29162   return stratify;
29163 };
29164
29165 function defaultSeparation$1(a, b) {
29166   return a.parent === b.parent ? 1 : 2;
29167 }
29168
29169 // function radialSeparation(a, b) {
29170 //   return (a.parent === b.parent ? 1 : 2) / a.depth;
29171 // }
29172
29173 // This function is used to traverse the left contour of a subtree (or
29174 // subforest). It returns the successor of v on this contour. This successor is
29175 // either given by the leftmost child of v or by the thread of v. The function
29176 // returns null if and only if v is on the highest level of its subtree.
29177 function nextLeft(v) {
29178   var children = v.children;
29179   return children ? children[0] : v.t;
29180 }
29181
29182 // This function works analogously to nextLeft.
29183 function nextRight(v) {
29184   var children = v.children;
29185   return children ? children[children.length - 1] : v.t;
29186 }
29187
29188 // Shifts the current subtree rooted at w+. This is done by increasing
29189 // prelim(w+) and mod(w+) by shift.
29190 function moveSubtree(wm, wp, shift) {
29191   var change = shift / (wp.i - wm.i);
29192   wp.c -= change;
29193   wp.s += shift;
29194   wm.c += change;
29195   wp.z += shift;
29196   wp.m += shift;
29197 }
29198
29199 // All other shifts, applied to the smaller subtrees between w- and w+, are
29200 // performed by this function. To prepare the shifts, we have to adjust
29201 // change(w+), shift(w+), and change(w-).
29202 function executeShifts(v) {
29203   var shift = 0,
29204       change = 0,
29205       children = v.children,
29206       i = children.length,
29207       w;
29208   while (--i >= 0) {
29209     w = children[i];
29210     w.z += shift;
29211     w.m += shift;
29212     shift += w.s + (change += w.c);
29213   }
29214 }
29215
29216 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29217 // returns the specified (default) ancestor.
29218 function nextAncestor(vim, v, ancestor) {
29219   return vim.a.parent === v.parent ? vim.a : ancestor;
29220 }
29221
29222 function TreeNode(node, i) {
29223   this._ = node;
29224   this.parent = null;
29225   this.children = null;
29226   this.A = null; // default ancestor
29227   this.a = this; // ancestor
29228   this.z = 0; // prelim
29229   this.m = 0; // mod
29230   this.c = 0; // change
29231   this.s = 0; // shift
29232   this.t = null; // thread
29233   this.i = i; // number
29234 }
29235
29236 TreeNode.prototype = Object.create(Node.prototype);
29237
29238 function treeRoot(root) {
29239   var tree = new TreeNode(root, 0),
29240       node,
29241       nodes = [tree],
29242       child,
29243       children,
29244       i,
29245       n;
29246
29247   while (node = nodes.pop()) {
29248     if (children = node._.children) {
29249       node.children = new Array(n = children.length);
29250       for (i = n - 1; i >= 0; --i) {
29251         nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29252         child.parent = node;
29253       }
29254     }
29255   }
29256
29257   (tree.parent = new TreeNode(null, 0)).children = [tree];
29258   return tree;
29259 }
29260
29261 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29262 var tree = function() {
29263   var separation = defaultSeparation$1,
29264       dx = 1,
29265       dy = 1,
29266       nodeSize = null;
29267
29268   function tree(root) {
29269     var t = treeRoot(root);
29270
29271     // Compute the layout using Buchheim et al.’s algorithm.
29272     t.eachAfter(firstWalk), t.parent.m = -t.z;
29273     t.eachBefore(secondWalk);
29274
29275     // If a fixed node size is specified, scale x and y.
29276     if (nodeSize) root.eachBefore(sizeNode);
29277
29278     // If a fixed tree size is specified, scale x and y based on the extent.
29279     // Compute the left-most, right-most, and depth-most nodes for extents.
29280     else {
29281       var left = root,
29282           right = root,
29283           bottom = root;
29284       root.eachBefore(function(node) {
29285         if (node.x < left.x) left = node;
29286         if (node.x > right.x) right = node;
29287         if (node.depth > bottom.depth) bottom = node;
29288       });
29289       var s = left === right ? 1 : separation(left, right) / 2,
29290           tx = s - left.x,
29291           kx = dx / (right.x + s + tx),
29292           ky = dy / (bottom.depth || 1);
29293       root.eachBefore(function(node) {
29294         node.x = (node.x + tx) * kx;
29295         node.y = node.depth * ky;
29296       });
29297     }
29298
29299     return root;
29300   }
29301
29302   // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29303   // applied recursively to the children of v, as well as the function
29304   // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29305   // node v is placed to the midpoint of its outermost children.
29306   function firstWalk(v) {
29307     var children = v.children,
29308         siblings = v.parent.children,
29309         w = v.i ? siblings[v.i - 1] : null;
29310     if (children) {
29311       executeShifts(v);
29312       var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29313       if (w) {
29314         v.z = w.z + separation(v._, w._);
29315         v.m = v.z - midpoint;
29316       } else {
29317         v.z = midpoint;
29318       }
29319     } else if (w) {
29320       v.z = w.z + separation(v._, w._);
29321     }
29322     v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29323   }
29324
29325   // Computes all real x-coordinates by summing up the modifiers recursively.
29326   function secondWalk(v) {
29327     v._.x = v.z + v.parent.m;
29328     v.m += v.parent.m;
29329   }
29330
29331   // The core of the algorithm. Here, a new subtree is combined with the
29332   // previous subtrees. Threads are used to traverse the inside and outside
29333   // contours of the left and right subtree up to the highest common level. The
29334   // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29335   // superscript o means outside and i means inside, the subscript - means left
29336   // subtree and + means right subtree. For summing up the modifiers along the
29337   // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29338   // nodes of the inside contours conflict, we compute the left one of the
29339   // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29340   // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29341   // Finally, we add a new thread (if necessary).
29342   function apportion(v, w, ancestor) {
29343     if (w) {
29344       var vip = v,
29345           vop = v,
29346           vim = w,
29347           vom = vip.parent.children[0],
29348           sip = vip.m,
29349           sop = vop.m,
29350           sim = vim.m,
29351           som = vom.m,
29352           shift;
29353       while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29354         vom = nextLeft(vom);
29355         vop = nextRight(vop);
29356         vop.a = v;
29357         shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29358         if (shift > 0) {
29359           moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29360           sip += shift;
29361           sop += shift;
29362         }
29363         sim += vim.m;
29364         sip += vip.m;
29365         som += vom.m;
29366         sop += vop.m;
29367       }
29368       if (vim && !nextRight(vop)) {
29369         vop.t = vim;
29370         vop.m += sim - sop;
29371       }
29372       if (vip && !nextLeft(vom)) {
29373         vom.t = vip;
29374         vom.m += sip - som;
29375         ancestor = v;
29376       }
29377     }
29378     return ancestor;
29379   }
29380
29381   function sizeNode(node) {
29382     node.x *= dx;
29383     node.y = node.depth * dy;
29384   }
29385
29386   tree.separation = function(x) {
29387     return arguments.length ? (separation = x, tree) : separation;
29388   };
29389
29390   tree.size = function(x) {
29391     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29392   };
29393
29394   tree.nodeSize = function(x) {
29395     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29396   };
29397
29398   return tree;
29399 };
29400
29401 var treemapSlice = function(parent, x0, y0, x1, y1) {
29402   var nodes = parent.children,
29403       node,
29404       i = -1,
29405       n = nodes.length,
29406       k = parent.value && (y1 - y0) / parent.value;
29407
29408   while (++i < n) {
29409     node = nodes[i], node.x0 = x0, node.x1 = x1;
29410     node.y0 = y0, node.y1 = y0 += node.value * k;
29411   }
29412 };
29413
29414 var phi = (1 + Math.sqrt(5)) / 2;
29415
29416 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29417   var rows = [],
29418       nodes = parent.children,
29419       row,
29420       nodeValue,
29421       i0 = 0,
29422       i1 = 0,
29423       n = nodes.length,
29424       dx, dy,
29425       value = parent.value,
29426       sumValue,
29427       minValue,
29428       maxValue,
29429       newRatio,
29430       minRatio,
29431       alpha,
29432       beta;
29433
29434   while (i0 < n) {
29435     dx = x1 - x0, dy = y1 - y0;
29436
29437     // Find the next non-empty node.
29438     do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
29439     minValue = maxValue = sumValue;
29440     alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29441     beta = sumValue * sumValue * alpha;
29442     minRatio = Math.max(maxValue / beta, beta / minValue);
29443
29444     // Keep adding nodes while the aspect ratio maintains or improves.
29445     for (; i1 < n; ++i1) {
29446       sumValue += nodeValue = nodes[i1].value;
29447       if (nodeValue < minValue) minValue = nodeValue;
29448       if (nodeValue > maxValue) maxValue = nodeValue;
29449       beta = sumValue * sumValue * alpha;
29450       newRatio = Math.max(maxValue / beta, beta / minValue);
29451       if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29452       minRatio = newRatio;
29453     }
29454
29455     // Position and record the row orientation.
29456     rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29457     if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29458     else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29459     value -= sumValue, i0 = i1;
29460   }
29461
29462   return rows;
29463 }
29464
29465 var squarify = ((function custom(ratio) {
29466
29467   function squarify(parent, x0, y0, x1, y1) {
29468     squarifyRatio(ratio, parent, x0, y0, x1, y1);
29469   }
29470
29471   squarify.ratio = function(x) {
29472     return custom((x = +x) > 1 ? x : 1);
29473   };
29474
29475   return squarify;
29476 }))(phi);
29477
29478 var index$6 = function() {
29479   var tile = squarify,
29480       round = false,
29481       dx = 1,
29482       dy = 1,
29483       paddingStack = [0],
29484       paddingInner = constantZero,
29485       paddingTop = constantZero,
29486       paddingRight = constantZero,
29487       paddingBottom = constantZero,
29488       paddingLeft = constantZero;
29489
29490   function treemap(root) {
29491     root.x0 =
29492     root.y0 = 0;
29493     root.x1 = dx;
29494     root.y1 = dy;
29495     root.eachBefore(positionNode);
29496     paddingStack = [0];
29497     if (round) root.eachBefore(roundNode);
29498     return root;
29499   }
29500
29501   function positionNode(node) {
29502     var p = paddingStack[node.depth],
29503         x0 = node.x0 + p,
29504         y0 = node.y0 + p,
29505         x1 = node.x1 - p,
29506         y1 = node.y1 - p;
29507     if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29508     if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29509     node.x0 = x0;
29510     node.y0 = y0;
29511     node.x1 = x1;
29512     node.y1 = y1;
29513     if (node.children) {
29514       p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29515       x0 += paddingLeft(node) - p;
29516       y0 += paddingTop(node) - p;
29517       x1 -= paddingRight(node) - p;
29518       y1 -= paddingBottom(node) - p;
29519       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29520       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29521       tile(node, x0, y0, x1, y1);
29522     }
29523   }
29524
29525   treemap.round = function(x) {
29526     return arguments.length ? (round = !!x, treemap) : round;
29527   };
29528
29529   treemap.size = function(x) {
29530     return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29531   };
29532
29533   treemap.tile = function(x) {
29534     return arguments.length ? (tile = required(x), treemap) : tile;
29535   };
29536
29537   treemap.padding = function(x) {
29538     return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29539   };
29540
29541   treemap.paddingInner = function(x) {
29542     return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner;
29543   };
29544
29545   treemap.paddingOuter = function(x) {
29546     return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29547   };
29548
29549   treemap.paddingTop = function(x) {
29550     return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop;
29551   };
29552
29553   treemap.paddingRight = function(x) {
29554     return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight;
29555   };
29556
29557   treemap.paddingBottom = function(x) {
29558     return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom;
29559   };
29560
29561   treemap.paddingLeft = function(x) {
29562     return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft;
29563   };
29564
29565   return treemap;
29566 };
29567
29568 var binary = function(parent, x0, y0, x1, y1) {
29569   var nodes = parent.children,
29570       i, n = nodes.length,
29571       sum, sums = new Array(n + 1);
29572
29573   for (sums[0] = sum = i = 0; i < n; ++i) {
29574     sums[i + 1] = sum += nodes[i].value;
29575   }
29576
29577   partition(0, n, parent.value, x0, y0, x1, y1);
29578
29579   function partition(i, j, value, x0, y0, x1, y1) {
29580     if (i >= j - 1) {
29581       var node = nodes[i];
29582       node.x0 = x0, node.y0 = y0;
29583       node.x1 = x1, node.y1 = y1;
29584       return;
29585     }
29586
29587     var valueOffset = sums[i],
29588         valueTarget = (value / 2) + valueOffset,
29589         k = i + 1,
29590         hi = j - 1;
29591
29592     while (k < hi) {
29593       var mid = k + hi >>> 1;
29594       if (sums[mid] < valueTarget) k = mid + 1;
29595       else hi = mid;
29596     }
29597
29598     var valueLeft = sums[k] - valueOffset,
29599         valueRight = value - valueLeft;
29600
29601     if ((y1 - y0) > (x1 - x0)) {
29602       var yk = (y0 * valueRight + y1 * valueLeft) / value;
29603       partition(i, k, valueLeft, x0, y0, x1, yk);
29604       partition(k, j, valueRight, x0, yk, x1, y1);
29605     } else {
29606       var xk = (x0 * valueRight + x1 * valueLeft) / value;
29607       partition(i, k, valueLeft, x0, y0, xk, y1);
29608       partition(k, j, valueRight, xk, y0, x1, y1);
29609     }
29610   }
29611 };
29612
29613 var sliceDice = function(parent, x0, y0, x1, y1) {
29614   (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
29615 };
29616
29617 var resquarify = ((function custom(ratio) {
29618
29619   function resquarify(parent, x0, y0, x1, y1) {
29620     if ((rows = parent._squarify) && (rows.ratio === ratio)) {
29621       var rows,
29622           row,
29623           nodes,
29624           i,
29625           j = -1,
29626           n,
29627           m = rows.length,
29628           value = parent.value;
29629
29630       while (++j < m) {
29631         row = rows[j], nodes = row.children;
29632         for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
29633         if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
29634         else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
29635         value -= row.value;
29636       }
29637     } else {
29638       parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
29639       rows.ratio = ratio;
29640     }
29641   }
29642
29643   resquarify.ratio = function(x) {
29644     return custom((x = +x) > 1 ? x : 1);
29645   };
29646
29647   return resquarify;
29648 }))(phi);
29649
29650 function basis$2(t1, v0, v1, v2, v3) {
29651   var t2 = t1 * t1, t3 = t2 * t1;
29652   return ((1 - 3 * t1 + 3 * t2 - t3) * v0
29653       + (4 - 6 * t2 + 3 * t3) * v1
29654       + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
29655       + t3 * v3) / 6;
29656 }
29657
29658 var basis$3 = function(values) {
29659   var n = values.length - 1;
29660   return function(t) {
29661     var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
29662         v1 = values[i],
29663         v2 = values[i + 1],
29664         v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
29665         v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
29666     return basis$2((t - i / n) * n, v0, v1, v2, v3);
29667   };
29668 };
29669
29670 var basisClosed$1 = function(values) {
29671   var n = values.length;
29672   return function(t) {
29673     var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
29674         v0 = values[(i + n - 1) % n],
29675         v1 = values[i % n],
29676         v2 = values[(i + 1) % n],
29677         v3 = values[(i + 2) % n];
29678     return basis$2((t - i / n) * n, v0, v1, v2, v3);
29679   };
29680 };
29681
29682 var constant$9 = function(x) {
29683   return function() {
29684     return x;
29685   };
29686 };
29687
29688 function linear$2(a, d) {
29689   return function(t) {
29690     return a + t * d;
29691   };
29692 }
29693
29694 function exponential$1(a, b, y) {
29695   return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
29696     return Math.pow(a + t * b, y);
29697   };
29698 }
29699
29700 function hue$1(a, b) {
29701   var d = b - a;
29702   return d ? linear$2(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$9(isNaN(a) ? b : a);
29703 }
29704
29705 function gamma$1(y) {
29706   return (y = +y) === 1 ? nogamma$1 : function(a, b) {
29707     return b - a ? exponential$1(a, b, y) : constant$9(isNaN(a) ? b : a);
29708   };
29709 }
29710
29711 function nogamma$1(a, b) {
29712   var d = b - a;
29713   return d ? linear$2(a, d) : constant$9(isNaN(a) ? b : a);
29714 }
29715
29716 var rgb$1 = ((function rgbGamma(y) {
29717   var color$$1 = gamma$1(y);
29718
29719   function rgb$$1(start, end) {
29720     var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
29721         g = color$$1(start.g, end.g),
29722         b = color$$1(start.b, end.b),
29723         opacity = nogamma$1(start.opacity, end.opacity);
29724     return function(t) {
29725       start.r = r(t);
29726       start.g = g(t);
29727       start.b = b(t);
29728       start.opacity = opacity(t);
29729       return start + "";
29730     };
29731   }
29732
29733   rgb$$1.gamma = rgbGamma;
29734
29735   return rgb$$1;
29736 }))(1);
29737
29738 function rgbSpline$1(spline) {
29739   return function(colors) {
29740     var n = colors.length,
29741         r = new Array(n),
29742         g = new Array(n),
29743         b = new Array(n),
29744         i, color$$1;
29745     for (i = 0; i < n; ++i) {
29746       color$$1 = rgb(colors[i]);
29747       r[i] = color$$1.r || 0;
29748       g[i] = color$$1.g || 0;
29749       b[i] = color$$1.b || 0;
29750     }
29751     r = spline(r);
29752     g = spline(g);
29753     b = spline(b);
29754     color$$1.opacity = 1;
29755     return function(t) {
29756       color$$1.r = r(t);
29757       color$$1.g = g(t);
29758       color$$1.b = b(t);
29759       return color$$1 + "";
29760     };
29761   };
29762 }
29763
29764 var rgbBasis$1 = rgbSpline$1(basis$3);
29765 var rgbBasisClosed$1 = rgbSpline$1(basisClosed$1);
29766
29767 var array$2 = function(a, b) {
29768   var nb = b ? b.length : 0,
29769       na = a ? Math.min(nb, a.length) : 0,
29770       x = new Array(nb),
29771       c = new Array(nb),
29772       i;
29773
29774   for (i = 0; i < na; ++i) x[i] = value$1(a[i], b[i]);
29775   for (; i < nb; ++i) c[i] = b[i];
29776
29777   return function(t) {
29778     for (i = 0; i < na; ++i) c[i] = x[i](t);
29779     return c;
29780   };
29781 };
29782
29783 var date$1 = function(a, b) {
29784   var d = new Date;
29785   return a = +a, b -= a, function(t) {
29786     return d.setTime(a + b * t), d;
29787   };
29788 };
29789
29790 var number$1 = function(a, b) {
29791   return a = +a, b -= a, function(t) {
29792     return a + b * t;
29793   };
29794 };
29795
29796 var object$2 = function(a, b) {
29797   var i = {},
29798       c = {},
29799       k;
29800
29801   if (a === null || typeof a !== "object") a = {};
29802   if (b === null || typeof b !== "object") b = {};
29803
29804   for (k in b) {
29805     if (k in a) {
29806       i[k] = value$1(a[k], b[k]);
29807     } else {
29808       c[k] = b[k];
29809     }
29810   }
29811
29812   return function(t) {
29813     for (k in i) c[k] = i[k](t);
29814     return c;
29815   };
29816 };
29817
29818 var reA$1 = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
29819 var reB$1 = new RegExp(reA$1.source, "g");
29820
29821 function zero$1(b) {
29822   return function() {
29823     return b;
29824   };
29825 }
29826
29827 function one$1(b) {
29828   return function(t) {
29829     return b(t) + "";
29830   };
29831 }
29832
29833 var string = function(a, b) {
29834   var bi = reA$1.lastIndex = reB$1.lastIndex = 0, // scan index for next number in b
29835       am, // current match in a
29836       bm, // current match in b
29837       bs, // string preceding current number in b, if any
29838       i = -1, // index in s
29839       s = [], // string constants and placeholders
29840       q = []; // number interpolators
29841
29842   // Coerce inputs to strings.
29843   a = a + "", b = b + "";
29844
29845   // Interpolate pairs of numbers in a & b.
29846   while ((am = reA$1.exec(a))
29847       && (bm = reB$1.exec(b))) {
29848     if ((bs = bm.index) > bi) { // a string precedes the next number in b
29849       bs = b.slice(bi, bs);
29850       if (s[i]) s[i] += bs; // coalesce with previous string
29851       else s[++i] = bs;
29852     }
29853     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
29854       if (s[i]) s[i] += bm; // coalesce with previous string
29855       else s[++i] = bm;
29856     } else { // interpolate non-matching numbers
29857       s[++i] = null;
29858       q.push({i: i, x: number$1(am, bm)});
29859     }
29860     bi = reB$1.lastIndex;
29861   }
29862
29863   // Add remains of b.
29864   if (bi < b.length) {
29865     bs = b.slice(bi);
29866     if (s[i]) s[i] += bs; // coalesce with previous string
29867     else s[++i] = bs;
29868   }
29869
29870   // Special optimization for only a single match.
29871   // Otherwise, interpolate each of the numbers and rejoin the string.
29872   return s.length < 2 ? (q[0]
29873       ? one$1(q[0].x)
29874       : zero$1(b))
29875       : (b = q.length, function(t) {
29876           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
29877           return s.join("");
29878         });
29879 };
29880
29881 var value$1 = function(a, b) {
29882   var t = typeof b, c;
29883   return b == null || t === "boolean" ? constant$9(b)
29884       : (t === "number" ? number$1
29885       : t === "string" ? ((c = color(b)) ? (b = c, rgb$1) : string)
29886       : b instanceof color ? rgb$1
29887       : b instanceof Date ? date$1
29888       : Array.isArray(b) ? array$2
29889       : isNaN(b) ? object$2
29890       : number$1)(a, b);
29891 };
29892
29893 var round = function(a, b) {
29894   return a = +a, b -= a, function(t) {
29895     return Math.round(a + b * t);
29896   };
29897 };
29898
29899 var degrees$2 = 180 / Math.PI;
29900
29901 var identity$6 = {
29902   translateX: 0,
29903   translateY: 0,
29904   rotate: 0,
29905   skewX: 0,
29906   scaleX: 1,
29907   scaleY: 1
29908 };
29909
29910 var decompose$1 = function(a, b, c, d, e, f) {
29911   var scaleX, scaleY, skewX;
29912   if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
29913   if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
29914   if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
29915   if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
29916   return {
29917     translateX: e,
29918     translateY: f,
29919     rotate: Math.atan2(b, a) * degrees$2,
29920     skewX: Math.atan(skewX) * degrees$2,
29921     scaleX: scaleX,
29922     scaleY: scaleY
29923   };
29924 };
29925
29926 var cssNode$1;
29927 var cssRoot$1;
29928 var cssView$1;
29929 var svgNode$1;
29930
29931 function parseCss$1(value) {
29932   if (value === "none") return identity$6;
29933   if (!cssNode$1) cssNode$1 = document.createElement("DIV"), cssRoot$1 = document.documentElement, cssView$1 = document.defaultView;
29934   cssNode$1.style.transform = value;
29935   value = cssView$1.getComputedStyle(cssRoot$1.appendChild(cssNode$1), null).getPropertyValue("transform");
29936   cssRoot$1.removeChild(cssNode$1);
29937   value = value.slice(7, -1).split(",");
29938   return decompose$1(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
29939 }
29940
29941 function parseSvg$1(value) {
29942   if (value == null) return identity$6;
29943   if (!svgNode$1) svgNode$1 = document.createElementNS("http://www.w3.org/2000/svg", "g");
29944   svgNode$1.setAttribute("transform", value);
29945   if (!(value = svgNode$1.transform.baseVal.consolidate())) return identity$6;
29946   value = value.matrix;
29947   return decompose$1(value.a, value.b, value.c, value.d, value.e, value.f);
29948 }
29949
29950 function interpolateTransform$1(parse, pxComma, pxParen, degParen) {
29951
29952   function pop(s) {
29953     return s.length ? s.pop() + " " : "";
29954   }
29955
29956   function translate(xa, ya, xb, yb, s, q) {
29957     if (xa !== xb || ya !== yb) {
29958       var i = s.push("translate(", null, pxComma, null, pxParen);
29959       q.push({i: i - 4, x: number$1(xa, xb)}, {i: i - 2, x: number$1(ya, yb)});
29960     } else if (xb || yb) {
29961       s.push("translate(" + xb + pxComma + yb + pxParen);
29962     }
29963   }
29964
29965   function rotate(a, b, s, q) {
29966     if (a !== b) {
29967       if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
29968       q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number$1(a, b)});
29969     } else if (b) {
29970       s.push(pop(s) + "rotate(" + b + degParen);
29971     }
29972   }
29973
29974   function skewX(a, b, s, q) {
29975     if (a !== b) {
29976       q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number$1(a, b)});
29977     } else if (b) {
29978       s.push(pop(s) + "skewX(" + b + degParen);
29979     }
29980   }
29981
29982   function scale(xa, ya, xb, yb, s, q) {
29983     if (xa !== xb || ya !== yb) {
29984       var i = s.push(pop(s) + "scale(", null, ",", null, ")");
29985       q.push({i: i - 4, x: number$1(xa, xb)}, {i: i - 2, x: number$1(ya, yb)});
29986     } else if (xb !== 1 || yb !== 1) {
29987       s.push(pop(s) + "scale(" + xb + "," + yb + ")");
29988     }
29989   }
29990
29991   return function(a, b) {
29992     var s = [], // string constants and placeholders
29993         q = []; // number interpolators
29994     a = parse(a), b = parse(b);
29995     translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
29996     rotate(a.rotate, b.rotate, s, q);
29997     skewX(a.skewX, b.skewX, s, q);
29998     scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
29999     a = b = null; // gc
30000     return function(t) {
30001       var i = -1, n = q.length, o;
30002       while (++i < n) s[(o = q[i]).i] = o.x(t);
30003       return s.join("");
30004     };
30005   };
30006 }
30007
30008 var interpolateTransformCss$1 = interpolateTransform$1(parseCss$1, "px, ", "px)", "deg)");
30009 var interpolateTransformSvg$1 = interpolateTransform$1(parseSvg$1, ", ", ")", ")");
30010
30011 var rho$1 = Math.SQRT2;
30012 var rho2$1 = 2;
30013 var rho4$1 = 4;
30014 var epsilon2$2 = 1e-12;
30015
30016 function cosh$1(x) {
30017   return ((x = Math.exp(x)) + 1 / x) / 2;
30018 }
30019
30020 function sinh$1(x) {
30021   return ((x = Math.exp(x)) - 1 / x) / 2;
30022 }
30023
30024 function tanh$1(x) {
30025   return ((x = Math.exp(2 * x)) - 1) / (x + 1);
30026 }
30027
30028 // p0 = [ux0, uy0, w0]
30029 // p1 = [ux1, uy1, w1]
30030 var interpolateZoom = function(p0, p1) {
30031   var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
30032       ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
30033       dx = ux1 - ux0,
30034       dy = uy1 - uy0,
30035       d2 = dx * dx + dy * dy,
30036       i,
30037       S;
30038
30039   // Special case for u0 ≅ u1.
30040   if (d2 < epsilon2$2) {
30041     S = Math.log(w1 / w0) / rho$1;
30042     i = function(t) {
30043       return [
30044         ux0 + t * dx,
30045         uy0 + t * dy,
30046         w0 * Math.exp(rho$1 * t * S)
30047       ];
30048     };
30049   }
30050
30051   // General case.
30052   else {
30053     var d1 = Math.sqrt(d2),
30054         b0 = (w1 * w1 - w0 * w0 + rho4$1 * d2) / (2 * w0 * rho2$1 * d1),
30055         b1 = (w1 * w1 - w0 * w0 - rho4$1 * d2) / (2 * w1 * rho2$1 * d1),
30056         r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
30057         r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
30058     S = (r1 - r0) / rho$1;
30059     i = function(t) {
30060       var s = t * S,
30061           coshr0 = cosh$1(r0),
30062           u = w0 / (rho2$1 * d1) * (coshr0 * tanh$1(rho$1 * s + r0) - sinh$1(r0));
30063       return [
30064         ux0 + u * dx,
30065         uy0 + u * dy,
30066         w0 * coshr0 / cosh$1(rho$1 * s + r0)
30067       ];
30068     };
30069   }
30070
30071   i.duration = S * 1000;
30072
30073   return i;
30074 };
30075
30076 function hsl$3(hue$$1) {
30077   return function(start, end) {
30078     var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
30079         s = nogamma$1(start.s, end.s),
30080         l = nogamma$1(start.l, end.l),
30081         opacity = nogamma$1(start.opacity, end.opacity);
30082     return function(t) {
30083       start.h = h(t);
30084       start.s = s(t);
30085       start.l = l(t);
30086       start.opacity = opacity(t);
30087       return start + "";
30088     };
30089   }
30090 }
30091
30092 var hsl$4 = hsl$3(hue$1);
30093 var hslLong$1 = hsl$3(nogamma$1);
30094
30095 function lab$2(start, end) {
30096   var l = nogamma$1((start = lab(start)).l, (end = lab(end)).l),
30097       a = nogamma$1(start.a, end.a),
30098       b = nogamma$1(start.b, end.b),
30099       opacity = nogamma$1(start.opacity, end.opacity);
30100   return function(t) {
30101     start.l = l(t);
30102     start.a = a(t);
30103     start.b = b(t);
30104     start.opacity = opacity(t);
30105     return start + "";
30106   };
30107 }
30108
30109 function hcl$3(hue$$1) {
30110   return function(start, end) {
30111     var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
30112         c = nogamma$1(start.c, end.c),
30113         l = nogamma$1(start.l, end.l),
30114         opacity = nogamma$1(start.opacity, end.opacity);
30115     return function(t) {
30116       start.h = h(t);
30117       start.c = c(t);
30118       start.l = l(t);
30119       start.opacity = opacity(t);
30120       return start + "";
30121     };
30122   }
30123 }
30124
30125 var hcl$4 = hcl$3(hue$1);
30126 var hclLong$1 = hcl$3(nogamma$1);
30127
30128 function cubehelix$3(hue$$1) {
30129   return (function cubehelixGamma(y) {
30130     y = +y;
30131
30132     function cubehelix$$1(start, end) {
30133       var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
30134           s = nogamma$1(start.s, end.s),
30135           l = nogamma$1(start.l, end.l),
30136           opacity = nogamma$1(start.opacity, end.opacity);
30137       return function(t) {
30138         start.h = h(t);
30139         start.s = s(t);
30140         start.l = l(Math.pow(t, y));
30141         start.opacity = opacity(t);
30142         return start + "";
30143       };
30144     }
30145
30146     cubehelix$$1.gamma = cubehelixGamma;
30147
30148     return cubehelix$$1;
30149   })(1);
30150 }
30151
30152 var cubehelix$4 = cubehelix$3(hue$1);
30153 var cubehelixLong$1 = cubehelix$3(nogamma$1);
30154
30155 var quantize$1 = function(interpolator, n) {
30156   var samples = new Array(n);
30157   for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
30158   return samples;
30159 };
30160
30161 var d3polygonArea = function(polygon) {
30162   var i = -1,
30163       n = polygon.length,
30164       a,
30165       b = polygon[n - 1],
30166       area = 0;
30167
30168   while (++i < n) {
30169     a = b;
30170     b = polygon[i];
30171     area += a[1] * b[0] - a[0] * b[1];
30172   }
30173
30174   return area / 2;
30175 };
30176
30177 var d3polygonCentroid = function(polygon) {
30178   var i = -1,
30179       n = polygon.length,
30180       x = 0,
30181       y = 0,
30182       a,
30183       b = polygon[n - 1],
30184       c,
30185       k = 0;
30186
30187   while (++i < n) {
30188     a = b;
30189     b = polygon[i];
30190     k += c = a[0] * b[1] - b[0] * a[1];
30191     x += (a[0] + b[0]) * c;
30192     y += (a[1] + b[1]) * c;
30193   }
30194
30195   return k *= 3, [x / k, y / k];
30196 };
30197
30198 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
30199 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
30200 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
30201 // negative if clockwise, and zero if the points are collinear.
30202 var cross = function(a, b, c) {
30203   return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
30204 };
30205
30206 function lexicographicOrder(a, b) {
30207   return a[0] - b[0] || a[1] - b[1];
30208 }
30209
30210 // Computes the upper convex hull per the monotone chain algorithm.
30211 // Assumes points.length >= 3, is sorted by x, unique in y.
30212 // Returns an array of indices into points in left-to-right order.
30213 function computeUpperHullIndexes(points) {
30214   var n = points.length,
30215       indexes = [0, 1],
30216       size = 2;
30217
30218   for (var i = 2; i < n; ++i) {
30219     while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
30220     indexes[size++] = i;
30221   }
30222
30223   return indexes.slice(0, size); // remove popped points
30224 }
30225
30226 var d3polygonHull = function(points) {
30227   if ((n = points.length) < 3) return null;
30228
30229   var i,
30230       n,
30231       sortedPoints = new Array(n),
30232       flippedPoints = new Array(n);
30233
30234   for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
30235   sortedPoints.sort(lexicographicOrder);
30236   for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
30237
30238   var upperIndexes = computeUpperHullIndexes(sortedPoints),
30239       lowerIndexes = computeUpperHullIndexes(flippedPoints);
30240
30241   // Construct the hull polygon, removing possible duplicate endpoints.
30242   var skipLeft = lowerIndexes[0] === upperIndexes[0],
30243       skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
30244       hull = [];
30245
30246   // Add upper hull in right-to-l order.
30247   // Then add lower hull in left-to-right order.
30248   for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
30249   for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
30250
30251   return hull;
30252 };
30253
30254 var contains = function(polygon, point) {
30255   var n = polygon.length,
30256       p = polygon[n - 1],
30257       x = point[0], y = point[1],
30258       x0 = p[0], y0 = p[1],
30259       x1, y1,
30260       inside = false;
30261
30262   for (var i = 0; i < n; ++i) {
30263     p = polygon[i], x1 = p[0], y1 = p[1];
30264     if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
30265     x0 = x1, y0 = y1;
30266   }
30267
30268   return inside;
30269 };
30270
30271 var length$1 = function(polygon) {
30272   var i = -1,
30273       n = polygon.length,
30274       b = polygon[n - 1],
30275       xa,
30276       ya,
30277       xb = b[0],
30278       yb = b[1],
30279       perimeter = 0;
30280
30281   while (++i < n) {
30282     xa = xb;
30283     ya = yb;
30284     b = polygon[i];
30285     xb = b[0];
30286     yb = b[1];
30287     xa -= xb;
30288     ya -= yb;
30289     perimeter += Math.sqrt(xa * xa + ya * ya);
30290   }
30291
30292   return perimeter;
30293 };
30294
30295 var slice$3 = [].slice;
30296
30297 var noabort = {};
30298
30299 function Queue(size) {
30300   if (!(size >= 1)) throw new Error;
30301   this._size = size;
30302   this._call =
30303   this._error = null;
30304   this._tasks = [];
30305   this._data = [];
30306   this._waiting =
30307   this._active =
30308   this._ended =
30309   this._start = 0; // inside a synchronous task callback?
30310 }
30311
30312 Queue.prototype = queue.prototype = {
30313   constructor: Queue,
30314   defer: function(callback) {
30315     if (typeof callback !== "function" || this._call) throw new Error;
30316     if (this._error != null) return this;
30317     var t = slice$3.call(arguments, 1);
30318     t.push(callback);
30319     ++this._waiting, this._tasks.push(t);
30320     poke$1(this);
30321     return this;
30322   },
30323   abort: function() {
30324     if (this._error == null) abort(this, new Error("abort"));
30325     return this;
30326   },
30327   await: function(callback) {
30328     if (typeof callback !== "function" || this._call) throw new Error;
30329     this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
30330     maybeNotify(this);
30331     return this;
30332   },
30333   awaitAll: function(callback) {
30334     if (typeof callback !== "function" || this._call) throw new Error;
30335     this._call = callback;
30336     maybeNotify(this);
30337     return this;
30338   }
30339 };
30340
30341 function poke$1(q) {
30342   if (!q._start) {
30343     try { start$1(q); } // let the current task complete
30344     catch (e) {
30345       if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
30346       else if (!q._data) throw e; // await callback errored synchronously
30347     }
30348   }
30349 }
30350
30351 function start$1(q) {
30352   while (q._start = q._waiting && q._active < q._size) {
30353     var i = q._ended + q._active,
30354         t = q._tasks[i],
30355         j = t.length - 1,
30356         c = t[j];
30357     t[j] = end(q, i);
30358     --q._waiting, ++q._active;
30359     t = c.apply(null, t);
30360     if (!q._tasks[i]) continue; // task finished synchronously
30361     q._tasks[i] = t || noabort;
30362   }
30363 }
30364
30365 function end(q, i) {
30366   return function(e, r) {
30367     if (!q._tasks[i]) return; // ignore multiple callbacks
30368     --q._active, ++q._ended;
30369     q._tasks[i] = null;
30370     if (q._error != null) return; // ignore secondary errors
30371     if (e != null) {
30372       abort(q, e);
30373     } else {
30374       q._data[i] = r;
30375       if (q._waiting) poke$1(q);
30376       else maybeNotify(q);
30377     }
30378   };
30379 }
30380
30381 function abort(q, e) {
30382   var i = q._tasks.length, t;
30383   q._error = e; // ignore active callbacks
30384   q._data = undefined; // allow gc
30385   q._waiting = NaN; // prevent starting
30386
30387   while (--i >= 0) {
30388     if (t = q._tasks[i]) {
30389       q._tasks[i] = null;
30390       if (t.abort) {
30391         try { t.abort(); }
30392         catch (e) { /* ignore */ }
30393       }
30394     }
30395   }
30396
30397   q._active = NaN; // allow notification
30398   maybeNotify(q);
30399 }
30400
30401 function maybeNotify(q) {
30402   if (!q._active && q._call) {
30403     var d = q._data;
30404     q._data = undefined; // allow gc
30405     q._call(q._error, d);
30406   }
30407 }
30408
30409 function queue(concurrency) {
30410   return new Queue(arguments.length ? +concurrency : Infinity);
30411 }
30412
30413 var uniform = function(min, max) {
30414   min = min == null ? 0 : +min;
30415   max = max == null ? 1 : +max;
30416   if (arguments.length === 1) max = min, min = 0;
30417   else max -= min;
30418   return function() {
30419     return Math.random() * max + min;
30420   };
30421 };
30422
30423 var normal = function(mu, sigma) {
30424   var x, r;
30425   mu = mu == null ? 0 : +mu;
30426   sigma = sigma == null ? 1 : +sigma;
30427   return function() {
30428     var y;
30429
30430     // If available, use the second previously-generated uniform random.
30431     if (x != null) y = x, x = null;
30432
30433     // Otherwise, generate a new x and y.
30434     else do {
30435       x = Math.random() * 2 - 1;
30436       y = Math.random() * 2 - 1;
30437       r = x * x + y * y;
30438     } while (!r || r > 1);
30439
30440     return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
30441   };
30442 };
30443
30444 var logNormal = function() {
30445   var randomNormal = normal.apply(this, arguments);
30446   return function() {
30447     return Math.exp(randomNormal());
30448   };
30449 };
30450
30451 var irwinHall = function(n) {
30452   return function() {
30453     for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
30454     return sum;
30455   };
30456 };
30457
30458 var bates = function(n) {
30459   var randomIrwinHall = irwinHall(n);
30460   return function() {
30461     return randomIrwinHall() / n;
30462   };
30463 };
30464
30465 var exponential$2 = function(lambda) {
30466   return function() {
30467     return -Math.log(1 - Math.random()) / lambda;
30468   };
30469 };
30470
30471 var request = function(url, callback) {
30472   var request,
30473       event = dispatch("beforesend", "progress", "load", "error"),
30474       mimeType,
30475       headers = map$1(),
30476       xhr = new XMLHttpRequest,
30477       user = null,
30478       password = null,
30479       response,
30480       responseType,
30481       timeout = 0;
30482
30483   // If IE does not support CORS, use XDomainRequest.
30484   if (typeof XDomainRequest !== "undefined"
30485       && !("withCredentials" in xhr)
30486       && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
30487
30488   "onload" in xhr
30489       ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
30490       : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
30491
30492   function respond(o) {
30493     var status = xhr.status, result;
30494     if (!status && hasResponse(xhr)
30495         || status >= 200 && status < 300
30496         || status === 304) {
30497       if (response) {
30498         try {
30499           result = response.call(request, xhr);
30500         } catch (e) {
30501           event.call("error", request, e);
30502           return;
30503         }
30504       } else {
30505         result = xhr;
30506       }
30507       event.call("load", request, result);
30508     } else {
30509       event.call("error", request, o);
30510     }
30511   }
30512
30513   xhr.onprogress = function(e) {
30514     event.call("progress", request, e);
30515   };
30516
30517   request = {
30518     header: function(name, value) {
30519       name = (name + "").toLowerCase();
30520       if (arguments.length < 2) return headers.get(name);
30521       if (value == null) headers.remove(name);
30522       else headers.set(name, value + "");
30523       return request;
30524     },
30525
30526     // If mimeType is non-null and no Accept header is set, a default is used.
30527     mimeType: function(value) {
30528       if (!arguments.length) return mimeType;
30529       mimeType = value == null ? null : value + "";
30530       return request;
30531     },
30532
30533     // Specifies what type the response value should take;
30534     // for instance, arraybuffer, blob, document, or text.
30535     responseType: function(value) {
30536       if (!arguments.length) return responseType;
30537       responseType = value;
30538       return request;
30539     },
30540
30541     timeout: function(value) {
30542       if (!arguments.length) return timeout;
30543       timeout = +value;
30544       return request;
30545     },
30546
30547     user: function(value) {
30548       return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
30549     },
30550
30551     password: function(value) {
30552       return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
30553     },
30554
30555     // Specify how to convert the response content to a specific type;
30556     // changes the callback value on "load" events.
30557     response: function(value) {
30558       response = value;
30559       return request;
30560     },
30561
30562     // Alias for send("GET", …).
30563     get: function(data, callback) {
30564       return request.send("GET", data, callback);
30565     },
30566
30567     // Alias for send("POST", …).
30568     post: function(data, callback) {
30569       return request.send("POST", data, callback);
30570     },
30571
30572     // If callback is non-null, it will be used for error and load events.
30573     send: function(method, data, callback) {
30574       xhr.open(method, url, true, user, password);
30575       if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
30576       if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
30577       if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
30578       if (responseType != null) xhr.responseType = responseType;
30579       if (timeout > 0) xhr.timeout = timeout;
30580       if (callback == null && typeof data === "function") callback = data, data = null;
30581       if (callback != null && callback.length === 1) callback = fixCallback(callback);
30582       if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
30583       event.call("beforesend", request, xhr);
30584       xhr.send(data == null ? null : data);
30585       return request;
30586     },
30587
30588     abort: function() {
30589       xhr.abort();
30590       return request;
30591     },
30592
30593     on: function() {
30594       var value = event.on.apply(event, arguments);
30595       return value === event ? request : value;
30596     }
30597   };
30598
30599   if (callback != null) {
30600     if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30601     return request.get(callback);
30602   }
30603
30604   return request;
30605 };
30606
30607 function fixCallback(callback) {
30608   return function(error, xhr) {
30609     callback(error == null ? xhr : null);
30610   };
30611 }
30612
30613 function hasResponse(xhr) {
30614   var type = xhr.responseType;
30615   return type && type !== "text"
30616       ? xhr.response // null on error
30617       : xhr.responseText; // "" on error
30618 }
30619
30620 var type$3 = function(defaultMimeType, response) {
30621   return function(url, callback) {
30622     var r = request(url).mimeType(defaultMimeType).response(response);
30623     if (callback != null) {
30624       if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
30625       return r.get(callback);
30626     }
30627     return r;
30628   };
30629 };
30630
30631 var html = type$3("text/html", function(xhr) {
30632   return document.createRange().createContextualFragment(xhr.responseText);
30633 });
30634
30635 var json = type$3("application/json", function(xhr) {
30636   return JSON.parse(xhr.responseText);
30637 });
30638
30639 var text = type$3("text/plain", function(xhr) {
30640   return xhr.responseText;
30641 });
30642
30643 var xml = type$3("application/xml", function(xhr) {
30644   var xml = xhr.responseXML;
30645   if (!xml) throw new Error("parse error");
30646   return xml;
30647 });
30648
30649 var dsv$1 = function(defaultMimeType, parse) {
30650   return function(url, row, callback) {
30651     if (arguments.length < 3) callback = row, row = null;
30652     var r = request(url).mimeType(defaultMimeType);
30653     r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
30654     r.row(row);
30655     return callback ? r.get(callback) : r;
30656   };
30657 };
30658
30659 function responseOf(parse, row) {
30660   return function(request$$1) {
30661     return parse(request$$1.responseText, row);
30662   };
30663 }
30664
30665 var csv$1 = dsv$1("text/csv", csvParse);
30666
30667 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
30668
30669 var array$3 = Array.prototype;
30670
30671 var map$3 = array$3.map;
30672 var slice$4 = array$3.slice;
30673
30674 var implicit = {name: "implicit"};
30675
30676 function ordinal(range) {
30677   var index = map$1(),
30678       domain = [],
30679       unknown = implicit;
30680
30681   range = range == null ? [] : slice$4.call(range);
30682
30683   function scale(d) {
30684     var key = d + "", i = index.get(key);
30685     if (!i) {
30686       if (unknown !== implicit) return unknown;
30687       index.set(key, i = domain.push(d));
30688     }
30689     return range[(i - 1) % range.length];
30690   }
30691
30692   scale.domain = function(_) {
30693     if (!arguments.length) return domain.slice();
30694     domain = [], index = map$1();
30695     var i = -1, n = _.length, d, key;
30696     while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
30697     return scale;
30698   };
30699
30700   scale.range = function(_) {
30701     return arguments.length ? (range = slice$4.call(_), scale) : range.slice();
30702   };
30703
30704   scale.unknown = function(_) {
30705     return arguments.length ? (unknown = _, scale) : unknown;
30706   };
30707
30708   scale.copy = function() {
30709     return ordinal()
30710         .domain(domain)
30711         .range(range)
30712         .unknown(unknown);
30713   };
30714
30715   return scale;
30716 }
30717
30718 function band() {
30719   var scale = ordinal().unknown(undefined),
30720       domain = scale.domain,
30721       ordinalRange = scale.range,
30722       range$$1 = [0, 1],
30723       step,
30724       bandwidth,
30725       round = false,
30726       paddingInner = 0,
30727       paddingOuter = 0,
30728       align = 0.5;
30729
30730   delete scale.unknown;
30731
30732   function rescale() {
30733     var n = domain().length,
30734         reverse = range$$1[1] < range$$1[0],
30735         start = range$$1[reverse - 0],
30736         stop = range$$1[1 - reverse];
30737     step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
30738     if (round) step = Math.floor(step);
30739     start += (stop - start - step * (n - paddingInner)) * align;
30740     bandwidth = step * (1 - paddingInner);
30741     if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
30742     var values = sequence(n).map(function(i) { return start + step * i; });
30743     return ordinalRange(reverse ? values.reverse() : values);
30744   }
30745
30746   scale.domain = function(_) {
30747     return arguments.length ? (domain(_), rescale()) : domain();
30748   };
30749
30750   scale.range = function(_) {
30751     return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
30752   };
30753
30754   scale.rangeRound = function(_) {
30755     return range$$1 = [+_[0], +_[1]], round = true, rescale();
30756   };
30757
30758   scale.bandwidth = function() {
30759     return bandwidth;
30760   };
30761
30762   scale.step = function() {
30763     return step;
30764   };
30765
30766   scale.round = function(_) {
30767     return arguments.length ? (round = !!_, rescale()) : round;
30768   };
30769
30770   scale.padding = function(_) {
30771     return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30772   };
30773
30774   scale.paddingInner = function(_) {
30775     return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
30776   };
30777
30778   scale.paddingOuter = function(_) {
30779     return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
30780   };
30781
30782   scale.align = function(_) {
30783     return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
30784   };
30785
30786   scale.copy = function() {
30787     return band()
30788         .domain(domain())
30789         .range(range$$1)
30790         .round(round)
30791         .paddingInner(paddingInner)
30792         .paddingOuter(paddingOuter)
30793         .align(align);
30794   };
30795
30796   return rescale();
30797 }
30798
30799 function pointish(scale) {
30800   var copy = scale.copy;
30801
30802   scale.padding = scale.paddingOuter;
30803   delete scale.paddingInner;
30804   delete scale.paddingOuter;
30805
30806   scale.copy = function() {
30807     return pointish(copy());
30808   };
30809
30810   return scale;
30811 }
30812
30813 function point$1() {
30814   return pointish(band().paddingInner(1));
30815 }
30816
30817 var constant$10 = function(x) {
30818   return function() {
30819     return x;
30820   };
30821 };
30822
30823 var number$2 = function(x) {
30824   return +x;
30825 };
30826
30827 var unit = [0, 1];
30828
30829 function deinterpolateLinear(a, b) {
30830   return (b -= (a = +a))
30831       ? function(x) { return (x - a) / b; }
30832       : constant$10(b);
30833 }
30834
30835 function deinterpolateClamp(deinterpolate) {
30836   return function(a, b) {
30837     var d = deinterpolate(a = +a, b = +b);
30838     return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
30839   };
30840 }
30841
30842 function reinterpolateClamp(reinterpolate) {
30843   return function(a, b) {
30844     var r = reinterpolate(a = +a, b = +b);
30845     return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
30846   };
30847 }
30848
30849 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
30850   var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
30851   if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
30852   else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
30853   return function(x) { return r0(d0(x)); };
30854 }
30855
30856 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
30857   var j = Math.min(domain.length, range$$1.length) - 1,
30858       d = new Array(j),
30859       r = new Array(j),
30860       i = -1;
30861
30862   // Reverse descending domains.
30863   if (domain[j] < domain[0]) {
30864     domain = domain.slice().reverse();
30865     range$$1 = range$$1.slice().reverse();
30866   }
30867
30868   while (++i < j) {
30869     d[i] = deinterpolate(domain[i], domain[i + 1]);
30870     r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
30871   }
30872
30873   return function(x) {
30874     var i = bisectRight(domain, x, 1, j) - 1;
30875     return r[i](d[i](x));
30876   };
30877 }
30878
30879 function copy(source, target) {
30880   return target
30881       .domain(source.domain())
30882       .range(source.range())
30883       .interpolate(source.interpolate())
30884       .clamp(source.clamp());
30885 }
30886
30887 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
30888 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
30889 function continuous(deinterpolate, reinterpolate) {
30890   var domain = unit,
30891       range$$1 = unit,
30892       interpolate$$1 = interpolateValue,
30893       clamp = false,
30894       piecewise,
30895       output,
30896       input;
30897
30898   function rescale() {
30899     piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
30900     output = input = null;
30901     return scale;
30902   }
30903
30904   function scale(x) {
30905     return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
30906   }
30907
30908   scale.invert = function(y) {
30909     return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
30910   };
30911
30912   scale.domain = function(_) {
30913     return arguments.length ? (domain = map$3.call(_, number$2), rescale()) : domain.slice();
30914   };
30915
30916   scale.range = function(_) {
30917     return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
30918   };
30919
30920   scale.rangeRound = function(_) {
30921     return range$$1 = slice$4.call(_), interpolate$$1 = interpolateRound, rescale();
30922   };
30923
30924   scale.clamp = function(_) {
30925     return arguments.length ? (clamp = !!_, rescale()) : clamp;
30926   };
30927
30928   scale.interpolate = function(_) {
30929     return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
30930   };
30931
30932   return rescale();
30933 }
30934
30935 var tickFormat = function(domain, count, specifier) {
30936   var start = domain[0],
30937       stop = domain[domain.length - 1],
30938       step = tickStep(start, stop, count == null ? 10 : count),
30939       precision;
30940   specifier = formatSpecifier(specifier == null ? ",f" : specifier);
30941   switch (specifier.type) {
30942     case "s": {
30943       var value = Math.max(Math.abs(start), Math.abs(stop));
30944       if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
30945       return formatPrefix(specifier, value);
30946     }
30947     case "":
30948     case "e":
30949     case "g":
30950     case "p":
30951     case "r": {
30952       if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
30953       break;
30954     }
30955     case "f":
30956     case "%": {
30957       if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
30958       break;
30959     }
30960   }
30961   return format(specifier);
30962 };
30963
30964 function linearish(scale) {
30965   var domain = scale.domain;
30966
30967   scale.ticks = function(count) {
30968     var d = domain();
30969     return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
30970   };
30971
30972   scale.tickFormat = function(count, specifier) {
30973     return tickFormat(domain(), count, specifier);
30974   };
30975
30976   scale.nice = function(count) {
30977     var d = domain(),
30978         i = d.length - 1,
30979         n = count == null ? 10 : count,
30980         start = d[0],
30981         stop = d[i],
30982         step = tickStep(start, stop, n);
30983
30984     if (step) {
30985       step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
30986       d[0] = Math.floor(start / step) * step;
30987       d[i] = Math.ceil(stop / step) * step;
30988       domain(d);
30989     }
30990
30991     return scale;
30992   };
30993
30994   return scale;
30995 }
30996
30997 function linear$3() {
30998   var scale = continuous(deinterpolateLinear, reinterpolate);
30999
31000   scale.copy = function() {
31001     return copy(scale, linear$3());
31002   };
31003
31004   return linearish(scale);
31005 }
31006
31007 function identity$7() {
31008   var domain = [0, 1];
31009
31010   function scale(x) {
31011     return +x;
31012   }
31013
31014   scale.invert = scale;
31015
31016   scale.domain = scale.range = function(_) {
31017     return arguments.length ? (domain = map$3.call(_, number$2), scale) : domain.slice();
31018   };
31019
31020   scale.copy = function() {
31021     return identity$7().domain(domain);
31022   };
31023
31024   return linearish(scale);
31025 }
31026
31027 var nice = function(domain, interval) {
31028   domain = domain.slice();
31029
31030   var i0 = 0,
31031       i1 = domain.length - 1,
31032       x0 = domain[i0],
31033       x1 = domain[i1],
31034       t;
31035
31036   if (x1 < x0) {
31037     t = i0, i0 = i1, i1 = t;
31038     t = x0, x0 = x1, x1 = t;
31039   }
31040
31041   domain[i0] = interval.floor(x0);
31042   domain[i1] = interval.ceil(x1);
31043   return domain;
31044 };
31045
31046 function deinterpolate(a, b) {
31047   return (b = Math.log(b / a))
31048       ? function(x) { return Math.log(x / a) / b; }
31049       : constant$10(b);
31050 }
31051
31052 function reinterpolate$1(a, b) {
31053   return a < 0
31054       ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
31055       : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
31056 }
31057
31058 function pow10(x) {
31059   return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
31060 }
31061
31062 function powp(base) {
31063   return base === 10 ? pow10
31064       : base === Math.E ? Math.exp
31065       : function(x) { return Math.pow(base, x); };
31066 }
31067
31068 function logp(base) {
31069   return base === Math.E ? Math.log
31070       : base === 10 && Math.log10
31071       || base === 2 && Math.log2
31072       || (base = Math.log(base), function(x) { return Math.log(x) / base; });
31073 }
31074
31075 function reflect(f) {
31076   return function(x) {
31077     return -f(-x);
31078   };
31079 }
31080
31081 function log$1() {
31082   var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]),
31083       domain = scale.domain,
31084       base = 10,
31085       logs = logp(10),
31086       pows = powp(10);
31087
31088   function rescale() {
31089     logs = logp(base), pows = powp(base);
31090     if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
31091     return scale;
31092   }
31093
31094   scale.base = function(_) {
31095     return arguments.length ? (base = +_, rescale()) : base;
31096   };
31097
31098   scale.domain = function(_) {
31099     return arguments.length ? (domain(_), rescale()) : domain();
31100   };
31101
31102   scale.ticks = function(count) {
31103     var d = domain(),
31104         u = d[0],
31105         v = d[d.length - 1],
31106         r;
31107
31108     if (r = v < u) i = u, u = v, v = i;
31109
31110     var i = logs(u),
31111         j = logs(v),
31112         p,
31113         k,
31114         t,
31115         n = count == null ? 10 : +count,
31116         z = [];
31117
31118     if (!(base % 1) && j - i < n) {
31119       i = Math.round(i) - 1, j = Math.round(j) + 1;
31120       if (u > 0) for (; i < j; ++i) {
31121         for (k = 1, p = pows(i); k < base; ++k) {
31122           t = p * k;
31123           if (t < u) continue;
31124           if (t > v) break;
31125           z.push(t);
31126         }
31127       } else for (; i < j; ++i) {
31128         for (k = base - 1, p = pows(i); k >= 1; --k) {
31129           t = p * k;
31130           if (t < u) continue;
31131           if (t > v) break;
31132           z.push(t);
31133         }
31134       }
31135     } else {
31136       z = ticks(i, j, Math.min(j - i, n)).map(pows);
31137     }
31138
31139     return r ? z.reverse() : z;
31140   };
31141
31142   scale.tickFormat = function(count, specifier) {
31143     if (specifier == null) specifier = base === 10 ? ".0e" : ",";
31144     if (typeof specifier !== "function") specifier = format(specifier);
31145     if (count === Infinity) return specifier;
31146     if (count == null) count = 10;
31147     var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
31148     return function(d) {
31149       var i = d / pows(Math.round(logs(d)));
31150       if (i * base < base - 0.5) i *= base;
31151       return i <= k ? specifier(d) : "";
31152     };
31153   };
31154
31155   scale.nice = function() {
31156     return domain(nice(domain(), {
31157       floor: function(x) { return pows(Math.floor(logs(x))); },
31158       ceil: function(x) { return pows(Math.ceil(logs(x))); }
31159     }));
31160   };
31161
31162   scale.copy = function() {
31163     return copy(scale, log$1().base(base));
31164   };
31165
31166   return scale;
31167 }
31168
31169 function raise$1(x, exponent) {
31170   return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
31171 }
31172
31173 function pow$1() {
31174   var exponent = 1,
31175       scale = continuous(deinterpolate, reinterpolate),
31176       domain = scale.domain;
31177
31178   function deinterpolate(a, b) {
31179     return (b = raise$1(b, exponent) - (a = raise$1(a, exponent)))
31180         ? function(x) { return (raise$1(x, exponent) - a) / b; }
31181         : constant$10(b);
31182   }
31183
31184   function reinterpolate(a, b) {
31185     b = raise$1(b, exponent) - (a = raise$1(a, exponent));
31186     return function(t) { return raise$1(a + b * t, 1 / exponent); };
31187   }
31188
31189   scale.exponent = function(_) {
31190     return arguments.length ? (exponent = +_, domain(domain())) : exponent;
31191   };
31192
31193   scale.copy = function() {
31194     return copy(scale, pow$1().exponent(exponent));
31195   };
31196
31197   return linearish(scale);
31198 }
31199
31200 function sqrt$1() {
31201   return pow$1().exponent(0.5);
31202 }
31203
31204 function quantile$$1() {
31205   var domain = [],
31206       range$$1 = [],
31207       thresholds = [];
31208
31209   function rescale() {
31210     var i = 0, n = Math.max(1, range$$1.length);
31211     thresholds = new Array(n - 1);
31212     while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
31213     return scale;
31214   }
31215
31216   function scale(x) {
31217     if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
31218   }
31219
31220   scale.invertExtent = function(y) {
31221     var i = range$$1.indexOf(y);
31222     return i < 0 ? [NaN, NaN] : [
31223       i > 0 ? thresholds[i - 1] : domain[0],
31224       i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
31225     ];
31226   };
31227
31228   scale.domain = function(_) {
31229     if (!arguments.length) return domain.slice();
31230     domain = [];
31231     for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
31232     domain.sort(ascending);
31233     return rescale();
31234   };
31235
31236   scale.range = function(_) {
31237     return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice();
31238   };
31239
31240   scale.quantiles = function() {
31241     return thresholds.slice();
31242   };
31243
31244   scale.copy = function() {
31245     return quantile$$1()
31246         .domain(domain)
31247         .range(range$$1);
31248   };
31249
31250   return scale;
31251 }
31252
31253 function quantize$2() {
31254   var x0 = 0,
31255       x1 = 1,
31256       n = 1,
31257       domain = [0.5],
31258       range$$1 = [0, 1];
31259
31260   function scale(x) {
31261     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31262   }
31263
31264   function rescale() {
31265     var i = -1;
31266     domain = new Array(n);
31267     while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
31268     return scale;
31269   }
31270
31271   scale.domain = function(_) {
31272     return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
31273   };
31274
31275   scale.range = function(_) {
31276     return arguments.length ? (n = (range$$1 = slice$4.call(_)).length - 1, rescale()) : range$$1.slice();
31277   };
31278
31279   scale.invertExtent = function(y) {
31280     var i = range$$1.indexOf(y);
31281     return i < 0 ? [NaN, NaN]
31282         : i < 1 ? [x0, domain[0]]
31283         : i >= n ? [domain[n - 1], x1]
31284         : [domain[i - 1], domain[i]];
31285   };
31286
31287   scale.copy = function() {
31288     return quantize$2()
31289         .domain([x0, x1])
31290         .range(range$$1);
31291   };
31292
31293   return linearish(scale);
31294 }
31295
31296 function threshold$1() {
31297   var domain = [0.5],
31298       range$$1 = [0, 1],
31299       n = 1;
31300
31301   function scale(x) {
31302     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
31303   }
31304
31305   scale.domain = function(_) {
31306     return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
31307   };
31308
31309   scale.range = function(_) {
31310     return arguments.length ? (range$$1 = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
31311   };
31312
31313   scale.invertExtent = function(y) {
31314     var i = range$$1.indexOf(y);
31315     return [domain[i - 1], domain[i]];
31316   };
31317
31318   scale.copy = function() {
31319     return threshold$1()
31320         .domain(domain)
31321         .range(range$$1);
31322   };
31323
31324   return scale;
31325 }
31326
31327 var t0$1 = new Date;
31328 var t1$1 = new Date;
31329
31330 function newInterval(floori, offseti, count, field) {
31331
31332   function interval(date) {
31333     return floori(date = new Date(+date)), date;
31334   }
31335
31336   interval.floor = interval;
31337
31338   interval.ceil = function(date) {
31339     return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
31340   };
31341
31342   interval.round = function(date) {
31343     var d0 = interval(date),
31344         d1 = interval.ceil(date);
31345     return date - d0 < d1 - date ? d0 : d1;
31346   };
31347
31348   interval.offset = function(date, step) {
31349     return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
31350   };
31351
31352   interval.range = function(start, stop, step) {
31353     var range = [];
31354     start = interval.ceil(start);
31355     step = step == null ? 1 : Math.floor(step);
31356     if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
31357     do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
31358     return range;
31359   };
31360
31361   interval.filter = function(test) {
31362     return newInterval(function(date) {
31363       if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
31364     }, function(date, step) {
31365       if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
31366     });
31367   };
31368
31369   if (count) {
31370     interval.count = function(start, end) {
31371       t0$1.setTime(+start), t1$1.setTime(+end);
31372       floori(t0$1), floori(t1$1);
31373       return Math.floor(count(t0$1, t1$1));
31374     };
31375
31376     interval.every = function(step) {
31377       step = Math.floor(step);
31378       return !isFinite(step) || !(step > 0) ? null
31379           : !(step > 1) ? interval
31380           : interval.filter(field
31381               ? function(d) { return field(d) % step === 0; }
31382               : function(d) { return interval.count(0, d) % step === 0; });
31383     };
31384   }
31385
31386   return interval;
31387 }
31388
31389 var millisecond = newInterval(function() {
31390   // noop
31391 }, function(date, step) {
31392   date.setTime(+date + step);
31393 }, function(start, end) {
31394   return end - start;
31395 });
31396
31397 // An optimized implementation for this simple case.
31398 millisecond.every = function(k) {
31399   k = Math.floor(k);
31400   if (!isFinite(k) || !(k > 0)) return null;
31401   if (!(k > 1)) return millisecond;
31402   return newInterval(function(date) {
31403     date.setTime(Math.floor(date / k) * k);
31404   }, function(date, step) {
31405     date.setTime(+date + step * k);
31406   }, function(start, end) {
31407     return (end - start) / k;
31408   });
31409 };
31410
31411 var milliseconds = millisecond.range;
31412
31413 var durationSecond$1 = 1e3;
31414 var durationMinute$1 = 6e4;
31415 var durationHour$1 = 36e5;
31416 var durationDay$1 = 864e5;
31417 var durationWeek$1 = 6048e5;
31418
31419 var second = newInterval(function(date) {
31420   date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1);
31421 }, function(date, step) {
31422   date.setTime(+date + step * durationSecond$1);
31423 }, function(start, end) {
31424   return (end - start) / durationSecond$1;
31425 }, function(date) {
31426   return date.getUTCSeconds();
31427 });
31428
31429 var seconds = second.range;
31430
31431 var minute = newInterval(function(date) {
31432   date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1);
31433 }, function(date, step) {
31434   date.setTime(+date + step * durationMinute$1);
31435 }, function(start, end) {
31436   return (end - start) / durationMinute$1;
31437 }, function(date) {
31438   return date.getMinutes();
31439 });
31440
31441 var minutes = minute.range;
31442
31443 var hour = newInterval(function(date) {
31444   var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1;
31445   if (offset < 0) offset += durationHour$1;
31446   date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset);
31447 }, function(date, step) {
31448   date.setTime(+date + step * durationHour$1);
31449 }, function(start, end) {
31450   return (end - start) / durationHour$1;
31451 }, function(date) {
31452   return date.getHours();
31453 });
31454
31455 var hours = hour.range;
31456
31457 var day = newInterval(function(date) {
31458   date.setHours(0, 0, 0, 0);
31459 }, function(date, step) {
31460   date.setDate(date.getDate() + step);
31461 }, function(start, end) {
31462   return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1;
31463 }, function(date) {
31464   return date.getDate() - 1;
31465 });
31466
31467 var days = day.range;
31468
31469 function weekday(i) {
31470   return newInterval(function(date) {
31471     date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
31472     date.setHours(0, 0, 0, 0);
31473   }, function(date, step) {
31474     date.setDate(date.getDate() + step * 7);
31475   }, function(start, end) {
31476     return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1;
31477   });
31478 }
31479
31480 var sunday = weekday(0);
31481 var monday = weekday(1);
31482 var tuesday = weekday(2);
31483 var wednesday = weekday(3);
31484 var thursday = weekday(4);
31485 var friday = weekday(5);
31486 var saturday = weekday(6);
31487
31488 var sundays = sunday.range;
31489 var mondays = monday.range;
31490 var tuesdays = tuesday.range;
31491 var wednesdays = wednesday.range;
31492 var thursdays = thursday.range;
31493 var fridays = friday.range;
31494 var saturdays = saturday.range;
31495
31496 var month = newInterval(function(date) {
31497   date.setDate(1);
31498   date.setHours(0, 0, 0, 0);
31499 }, function(date, step) {
31500   date.setMonth(date.getMonth() + step);
31501 }, function(start, end) {
31502   return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
31503 }, function(date) {
31504   return date.getMonth();
31505 });
31506
31507 var months = month.range;
31508
31509 var year = newInterval(function(date) {
31510   date.setMonth(0, 1);
31511   date.setHours(0, 0, 0, 0);
31512 }, function(date, step) {
31513   date.setFullYear(date.getFullYear() + step);
31514 }, function(start, end) {
31515   return end.getFullYear() - start.getFullYear();
31516 }, function(date) {
31517   return date.getFullYear();
31518 });
31519
31520 // An optimized implementation for this simple case.
31521 year.every = function(k) {
31522   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31523     date.setFullYear(Math.floor(date.getFullYear() / k) * k);
31524     date.setMonth(0, 1);
31525     date.setHours(0, 0, 0, 0);
31526   }, function(date, step) {
31527     date.setFullYear(date.getFullYear() + step * k);
31528   });
31529 };
31530
31531 var years = year.range;
31532
31533 var utcMinute = newInterval(function(date) {
31534   date.setUTCSeconds(0, 0);
31535 }, function(date, step) {
31536   date.setTime(+date + step * durationMinute$1);
31537 }, function(start, end) {
31538   return (end - start) / durationMinute$1;
31539 }, function(date) {
31540   return date.getUTCMinutes();
31541 });
31542
31543 var utcMinutes = utcMinute.range;
31544
31545 var utcHour = newInterval(function(date) {
31546   date.setUTCMinutes(0, 0, 0);
31547 }, function(date, step) {
31548   date.setTime(+date + step * durationHour$1);
31549 }, function(start, end) {
31550   return (end - start) / durationHour$1;
31551 }, function(date) {
31552   return date.getUTCHours();
31553 });
31554
31555 var utcHours = utcHour.range;
31556
31557 var utcDay = newInterval(function(date) {
31558   date.setUTCHours(0, 0, 0, 0);
31559 }, function(date, step) {
31560   date.setUTCDate(date.getUTCDate() + step);
31561 }, function(start, end) {
31562   return (end - start) / durationDay$1;
31563 }, function(date) {
31564   return date.getUTCDate() - 1;
31565 });
31566
31567 var utcDays = utcDay.range;
31568
31569 function utcWeekday(i) {
31570   return newInterval(function(date) {
31571     date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
31572     date.setUTCHours(0, 0, 0, 0);
31573   }, function(date, step) {
31574     date.setUTCDate(date.getUTCDate() + step * 7);
31575   }, function(start, end) {
31576     return (end - start) / durationWeek$1;
31577   });
31578 }
31579
31580 var utcSunday = utcWeekday(0);
31581 var utcMonday = utcWeekday(1);
31582 var utcTuesday = utcWeekday(2);
31583 var utcWednesday = utcWeekday(3);
31584 var utcThursday = utcWeekday(4);
31585 var utcFriday = utcWeekday(5);
31586 var utcSaturday = utcWeekday(6);
31587
31588 var utcSundays = utcSunday.range;
31589 var utcMondays = utcMonday.range;
31590 var utcTuesdays = utcTuesday.range;
31591 var utcWednesdays = utcWednesday.range;
31592 var utcThursdays = utcThursday.range;
31593 var utcFridays = utcFriday.range;
31594 var utcSaturdays = utcSaturday.range;
31595
31596 var utcMonth = newInterval(function(date) {
31597   date.setUTCDate(1);
31598   date.setUTCHours(0, 0, 0, 0);
31599 }, function(date, step) {
31600   date.setUTCMonth(date.getUTCMonth() + step);
31601 }, function(start, end) {
31602   return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
31603 }, function(date) {
31604   return date.getUTCMonth();
31605 });
31606
31607 var utcMonths = utcMonth.range;
31608
31609 var utcYear = newInterval(function(date) {
31610   date.setUTCMonth(0, 1);
31611   date.setUTCHours(0, 0, 0, 0);
31612 }, function(date, step) {
31613   date.setUTCFullYear(date.getUTCFullYear() + step);
31614 }, function(start, end) {
31615   return end.getUTCFullYear() - start.getUTCFullYear();
31616 }, function(date) {
31617   return date.getUTCFullYear();
31618 });
31619
31620 // An optimized implementation for this simple case.
31621 utcYear.every = function(k) {
31622   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
31623     date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
31624     date.setUTCMonth(0, 1);
31625     date.setUTCHours(0, 0, 0, 0);
31626   }, function(date, step) {
31627     date.setUTCFullYear(date.getUTCFullYear() + step * k);
31628   });
31629 };
31630
31631 var utcYears = utcYear.range;
31632
31633 function localDate(d) {
31634   if (0 <= d.y && d.y < 100) {
31635     var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
31636     date.setFullYear(d.y);
31637     return date;
31638   }
31639   return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
31640 }
31641
31642 function utcDate(d) {
31643   if (0 <= d.y && d.y < 100) {
31644     var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
31645     date.setUTCFullYear(d.y);
31646     return date;
31647   }
31648   return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
31649 }
31650
31651 function newYear(y) {
31652   return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
31653 }
31654
31655 function formatLocale$1(locale) {
31656   var locale_dateTime = locale.dateTime,
31657       locale_date = locale.date,
31658       locale_time = locale.time,
31659       locale_periods = locale.periods,
31660       locale_weekdays = locale.days,
31661       locale_shortWeekdays = locale.shortDays,
31662       locale_months = locale.months,
31663       locale_shortMonths = locale.shortMonths;
31664
31665   var periodRe = formatRe(locale_periods),
31666       periodLookup = formatLookup(locale_periods),
31667       weekdayRe = formatRe(locale_weekdays),
31668       weekdayLookup = formatLookup(locale_weekdays),
31669       shortWeekdayRe = formatRe(locale_shortWeekdays),
31670       shortWeekdayLookup = formatLookup(locale_shortWeekdays),
31671       monthRe = formatRe(locale_months),
31672       monthLookup = formatLookup(locale_months),
31673       shortMonthRe = formatRe(locale_shortMonths),
31674       shortMonthLookup = formatLookup(locale_shortMonths);
31675
31676   var formats = {
31677     "a": formatShortWeekday,
31678     "A": formatWeekday,
31679     "b": formatShortMonth,
31680     "B": formatMonth,
31681     "c": null,
31682     "d": formatDayOfMonth,
31683     "e": formatDayOfMonth,
31684     "H": formatHour24,
31685     "I": formatHour12,
31686     "j": formatDayOfYear,
31687     "L": formatMilliseconds,
31688     "m": formatMonthNumber,
31689     "M": formatMinutes,
31690     "p": formatPeriod,
31691     "S": formatSeconds,
31692     "U": formatWeekNumberSunday,
31693     "w": formatWeekdayNumber,
31694     "W": formatWeekNumberMonday,
31695     "x": null,
31696     "X": null,
31697     "y": formatYear,
31698     "Y": formatFullYear,
31699     "Z": formatZone,
31700     "%": formatLiteralPercent
31701   };
31702
31703   var utcFormats = {
31704     "a": formatUTCShortWeekday,
31705     "A": formatUTCWeekday,
31706     "b": formatUTCShortMonth,
31707     "B": formatUTCMonth,
31708     "c": null,
31709     "d": formatUTCDayOfMonth,
31710     "e": formatUTCDayOfMonth,
31711     "H": formatUTCHour24,
31712     "I": formatUTCHour12,
31713     "j": formatUTCDayOfYear,
31714     "L": formatUTCMilliseconds,
31715     "m": formatUTCMonthNumber,
31716     "M": formatUTCMinutes,
31717     "p": formatUTCPeriod,
31718     "S": formatUTCSeconds,
31719     "U": formatUTCWeekNumberSunday,
31720     "w": formatUTCWeekdayNumber,
31721     "W": formatUTCWeekNumberMonday,
31722     "x": null,
31723     "X": null,
31724     "y": formatUTCYear,
31725     "Y": formatUTCFullYear,
31726     "Z": formatUTCZone,
31727     "%": formatLiteralPercent
31728   };
31729
31730   var parses = {
31731     "a": parseShortWeekday,
31732     "A": parseWeekday,
31733     "b": parseShortMonth,
31734     "B": parseMonth,
31735     "c": parseLocaleDateTime,
31736     "d": parseDayOfMonth,
31737     "e": parseDayOfMonth,
31738     "H": parseHour24,
31739     "I": parseHour24,
31740     "j": parseDayOfYear,
31741     "L": parseMilliseconds,
31742     "m": parseMonthNumber,
31743     "M": parseMinutes,
31744     "p": parsePeriod,
31745     "S": parseSeconds,
31746     "U": parseWeekNumberSunday,
31747     "w": parseWeekdayNumber,
31748     "W": parseWeekNumberMonday,
31749     "x": parseLocaleDate,
31750     "X": parseLocaleTime,
31751     "y": parseYear,
31752     "Y": parseFullYear,
31753     "Z": parseZone,
31754     "%": parseLiteralPercent
31755   };
31756
31757   // These recursive directive definitions must be deferred.
31758   formats.x = newFormat(locale_date, formats);
31759   formats.X = newFormat(locale_time, formats);
31760   formats.c = newFormat(locale_dateTime, formats);
31761   utcFormats.x = newFormat(locale_date, utcFormats);
31762   utcFormats.X = newFormat(locale_time, utcFormats);
31763   utcFormats.c = newFormat(locale_dateTime, utcFormats);
31764
31765   function newFormat(specifier, formats) {
31766     return function(date) {
31767       var string = [],
31768           i = -1,
31769           j = 0,
31770           n = specifier.length,
31771           c,
31772           pad,
31773           format;
31774
31775       if (!(date instanceof Date)) date = new Date(+date);
31776
31777       while (++i < n) {
31778         if (specifier.charCodeAt(i) === 37) {
31779           string.push(specifier.slice(j, i));
31780           if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
31781           else pad = c === "e" ? " " : "0";
31782           if (format = formats[c]) c = format(date, pad);
31783           string.push(c);
31784           j = i + 1;
31785         }
31786       }
31787
31788       string.push(specifier.slice(j, i));
31789       return string.join("");
31790     };
31791   }
31792
31793   function newParse(specifier, newDate) {
31794     return function(string) {
31795       var d = newYear(1900),
31796           i = parseSpecifier(d, specifier, string += "", 0);
31797       if (i != string.length) return null;
31798
31799       // The am-pm flag is 0 for AM, and 1 for PM.
31800       if ("p" in d) d.H = d.H % 12 + d.p * 12;
31801
31802       // Convert day-of-week and week-of-year to day-of-year.
31803       if ("W" in d || "U" in d) {
31804         if (!("w" in d)) d.w = "W" in d ? 1 : 0;
31805         var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
31806         d.m = 0;
31807         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;
31808       }
31809
31810       // If a time zone is specified, all fields are interpreted as UTC and then
31811       // offset according to the specified time zone.
31812       if ("Z" in d) {
31813         d.H += d.Z / 100 | 0;
31814         d.M += d.Z % 100;
31815         return utcDate(d);
31816       }
31817
31818       // Otherwise, all fields are in local time.
31819       return newDate(d);
31820     };
31821   }
31822
31823   function parseSpecifier(d, specifier, string, j) {
31824     var i = 0,
31825         n = specifier.length,
31826         m = string.length,
31827         c,
31828         parse;
31829
31830     while (i < n) {
31831       if (j >= m) return -1;
31832       c = specifier.charCodeAt(i++);
31833       if (c === 37) {
31834         c = specifier.charAt(i++);
31835         parse = parses[c in pads ? specifier.charAt(i++) : c];
31836         if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
31837       } else if (c != string.charCodeAt(j++)) {
31838         return -1;
31839       }
31840     }
31841
31842     return j;
31843   }
31844
31845   function parsePeriod(d, string, i) {
31846     var n = periodRe.exec(string.slice(i));
31847     return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31848   }
31849
31850   function parseShortWeekday(d, string, i) {
31851     var n = shortWeekdayRe.exec(string.slice(i));
31852     return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31853   }
31854
31855   function parseWeekday(d, string, i) {
31856     var n = weekdayRe.exec(string.slice(i));
31857     return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31858   }
31859
31860   function parseShortMonth(d, string, i) {
31861     var n = shortMonthRe.exec(string.slice(i));
31862     return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31863   }
31864
31865   function parseMonth(d, string, i) {
31866     var n = monthRe.exec(string.slice(i));
31867     return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
31868   }
31869
31870   function parseLocaleDateTime(d, string, i) {
31871     return parseSpecifier(d, locale_dateTime, string, i);
31872   }
31873
31874   function parseLocaleDate(d, string, i) {
31875     return parseSpecifier(d, locale_date, string, i);
31876   }
31877
31878   function parseLocaleTime(d, string, i) {
31879     return parseSpecifier(d, locale_time, string, i);
31880   }
31881
31882   function formatShortWeekday(d) {
31883     return locale_shortWeekdays[d.getDay()];
31884   }
31885
31886   function formatWeekday(d) {
31887     return locale_weekdays[d.getDay()];
31888   }
31889
31890   function formatShortMonth(d) {
31891     return locale_shortMonths[d.getMonth()];
31892   }
31893
31894   function formatMonth(d) {
31895     return locale_months[d.getMonth()];
31896   }
31897
31898   function formatPeriod(d) {
31899     return locale_periods[+(d.getHours() >= 12)];
31900   }
31901
31902   function formatUTCShortWeekday(d) {
31903     return locale_shortWeekdays[d.getUTCDay()];
31904   }
31905
31906   function formatUTCWeekday(d) {
31907     return locale_weekdays[d.getUTCDay()];
31908   }
31909
31910   function formatUTCShortMonth(d) {
31911     return locale_shortMonths[d.getUTCMonth()];
31912   }
31913
31914   function formatUTCMonth(d) {
31915     return locale_months[d.getUTCMonth()];
31916   }
31917
31918   function formatUTCPeriod(d) {
31919     return locale_periods[+(d.getUTCHours() >= 12)];
31920   }
31921
31922   return {
31923     format: function(specifier) {
31924       var f = newFormat(specifier += "", formats);
31925       f.toString = function() { return specifier; };
31926       return f;
31927     },
31928     parse: function(specifier) {
31929       var p = newParse(specifier += "", localDate);
31930       p.toString = function() { return specifier; };
31931       return p;
31932     },
31933     utcFormat: function(specifier) {
31934       var f = newFormat(specifier += "", utcFormats);
31935       f.toString = function() { return specifier; };
31936       return f;
31937     },
31938     utcParse: function(specifier) {
31939       var p = newParse(specifier, utcDate);
31940       p.toString = function() { return specifier; };
31941       return p;
31942     }
31943   };
31944 }
31945
31946 var pads = {"-": "", "_": " ", "0": "0"};
31947 var numberRe = /^\s*\d+/;
31948 var percentRe = /^%/;
31949 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
31950
31951 function pad(value, fill, width) {
31952   var sign = value < 0 ? "-" : "",
31953       string = (sign ? -value : value) + "",
31954       length = string.length;
31955   return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
31956 }
31957
31958 function requote(s) {
31959   return s.replace(requoteRe, "\\$&");
31960 }
31961
31962 function formatRe(names) {
31963   return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
31964 }
31965
31966 function formatLookup(names) {
31967   var map = {}, i = -1, n = names.length;
31968   while (++i < n) map[names[i].toLowerCase()] = i;
31969   return map;
31970 }
31971
31972 function parseWeekdayNumber(d, string, i) {
31973   var n = numberRe.exec(string.slice(i, i + 1));
31974   return n ? (d.w = +n[0], i + n[0].length) : -1;
31975 }
31976
31977 function parseWeekNumberSunday(d, string, i) {
31978   var n = numberRe.exec(string.slice(i));
31979   return n ? (d.U = +n[0], i + n[0].length) : -1;
31980 }
31981
31982 function parseWeekNumberMonday(d, string, i) {
31983   var n = numberRe.exec(string.slice(i));
31984   return n ? (d.W = +n[0], i + n[0].length) : -1;
31985 }
31986
31987 function parseFullYear(d, string, i) {
31988   var n = numberRe.exec(string.slice(i, i + 4));
31989   return n ? (d.y = +n[0], i + n[0].length) : -1;
31990 }
31991
31992 function parseYear(d, string, i) {
31993   var n = numberRe.exec(string.slice(i, i + 2));
31994   return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
31995 }
31996
31997 function parseZone(d, string, i) {
31998   var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
31999   return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
32000 }
32001
32002 function parseMonthNumber(d, string, i) {
32003   var n = numberRe.exec(string.slice(i, i + 2));
32004   return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
32005 }
32006
32007 function parseDayOfMonth(d, string, i) {
32008   var n = numberRe.exec(string.slice(i, i + 2));
32009   return n ? (d.d = +n[0], i + n[0].length) : -1;
32010 }
32011
32012 function parseDayOfYear(d, string, i) {
32013   var n = numberRe.exec(string.slice(i, i + 3));
32014   return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
32015 }
32016
32017 function parseHour24(d, string, i) {
32018   var n = numberRe.exec(string.slice(i, i + 2));
32019   return n ? (d.H = +n[0], i + n[0].length) : -1;
32020 }
32021
32022 function parseMinutes(d, string, i) {
32023   var n = numberRe.exec(string.slice(i, i + 2));
32024   return n ? (d.M = +n[0], i + n[0].length) : -1;
32025 }
32026
32027 function parseSeconds(d, string, i) {
32028   var n = numberRe.exec(string.slice(i, i + 2));
32029   return n ? (d.S = +n[0], i + n[0].length) : -1;
32030 }
32031
32032 function parseMilliseconds(d, string, i) {
32033   var n = numberRe.exec(string.slice(i, i + 3));
32034   return n ? (d.L = +n[0], i + n[0].length) : -1;
32035 }
32036
32037 function parseLiteralPercent(d, string, i) {
32038   var n = percentRe.exec(string.slice(i, i + 1));
32039   return n ? i + n[0].length : -1;
32040 }
32041
32042 function formatDayOfMonth(d, p) {
32043   return pad(d.getDate(), p, 2);
32044 }
32045
32046 function formatHour24(d, p) {
32047   return pad(d.getHours(), p, 2);
32048 }
32049
32050 function formatHour12(d, p) {
32051   return pad(d.getHours() % 12 || 12, p, 2);
32052 }
32053
32054 function formatDayOfYear(d, p) {
32055   return pad(1 + day.count(year(d), d), p, 3);
32056 }
32057
32058 function formatMilliseconds(d, p) {
32059   return pad(d.getMilliseconds(), p, 3);
32060 }
32061
32062 function formatMonthNumber(d, p) {
32063   return pad(d.getMonth() + 1, p, 2);
32064 }
32065
32066 function formatMinutes(d, p) {
32067   return pad(d.getMinutes(), p, 2);
32068 }
32069
32070 function formatSeconds(d, p) {
32071   return pad(d.getSeconds(), p, 2);
32072 }
32073
32074 function formatWeekNumberSunday(d, p) {
32075   return pad(sunday.count(year(d), d), p, 2);
32076 }
32077
32078 function formatWeekdayNumber(d) {
32079   return d.getDay();
32080 }
32081
32082 function formatWeekNumberMonday(d, p) {
32083   return pad(monday.count(year(d), d), p, 2);
32084 }
32085
32086 function formatYear(d, p) {
32087   return pad(d.getFullYear() % 100, p, 2);
32088 }
32089
32090 function formatFullYear(d, p) {
32091   return pad(d.getFullYear() % 10000, p, 4);
32092 }
32093
32094 function formatZone(d) {
32095   var z = d.getTimezoneOffset();
32096   return (z > 0 ? "-" : (z *= -1, "+"))
32097       + pad(z / 60 | 0, "0", 2)
32098       + pad(z % 60, "0", 2);
32099 }
32100
32101 function formatUTCDayOfMonth(d, p) {
32102   return pad(d.getUTCDate(), p, 2);
32103 }
32104
32105 function formatUTCHour24(d, p) {
32106   return pad(d.getUTCHours(), p, 2);
32107 }
32108
32109 function formatUTCHour12(d, p) {
32110   return pad(d.getUTCHours() % 12 || 12, p, 2);
32111 }
32112
32113 function formatUTCDayOfYear(d, p) {
32114   return pad(1 + utcDay.count(utcYear(d), d), p, 3);
32115 }
32116
32117 function formatUTCMilliseconds(d, p) {
32118   return pad(d.getUTCMilliseconds(), p, 3);
32119 }
32120
32121 function formatUTCMonthNumber(d, p) {
32122   return pad(d.getUTCMonth() + 1, p, 2);
32123 }
32124
32125 function formatUTCMinutes(d, p) {
32126   return pad(d.getUTCMinutes(), p, 2);
32127 }
32128
32129 function formatUTCSeconds(d, p) {
32130   return pad(d.getUTCSeconds(), p, 2);
32131 }
32132
32133 function formatUTCWeekNumberSunday(d, p) {
32134   return pad(utcSunday.count(utcYear(d), d), p, 2);
32135 }
32136
32137 function formatUTCWeekdayNumber(d) {
32138   return d.getUTCDay();
32139 }
32140
32141 function formatUTCWeekNumberMonday(d, p) {
32142   return pad(utcMonday.count(utcYear(d), d), p, 2);
32143 }
32144
32145 function formatUTCYear(d, p) {
32146   return pad(d.getUTCFullYear() % 100, p, 2);
32147 }
32148
32149 function formatUTCFullYear(d, p) {
32150   return pad(d.getUTCFullYear() % 10000, p, 4);
32151 }
32152
32153 function formatUTCZone() {
32154   return "+0000";
32155 }
32156
32157 function formatLiteralPercent() {
32158   return "%";
32159 }
32160
32161 var locale$2;
32162 var timeFormat;
32163 var timeParse;
32164 var utcFormat;
32165 var utcParse;
32166
32167 defaultLocale$1({
32168   dateTime: "%x, %X",
32169   date: "%-m/%-d/%Y",
32170   time: "%-I:%M:%S %p",
32171   periods: ["AM", "PM"],
32172   days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
32173   shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
32174   months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
32175   shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
32176 });
32177
32178 function defaultLocale$1(definition) {
32179   locale$2 = formatLocale$1(definition);
32180   timeFormat = locale$2.format;
32181   timeParse = locale$2.parse;
32182   utcFormat = locale$2.utcFormat;
32183   utcParse = locale$2.utcParse;
32184   return locale$2;
32185 }
32186
32187 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
32188
32189 function formatIsoNative(date) {
32190   return date.toISOString();
32191 }
32192
32193 var formatIso = Date.prototype.toISOString
32194     ? formatIsoNative
32195     : utcFormat(isoSpecifier);
32196
32197 function parseIsoNative(string) {
32198   var date = new Date(string);
32199   return isNaN(date) ? null : date;
32200 }
32201
32202 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
32203     ? parseIsoNative
32204     : utcParse(isoSpecifier);
32205
32206 var durationSecond = 1000;
32207 var durationMinute = durationSecond * 60;
32208 var durationHour = durationMinute * 60;
32209 var durationDay = durationHour * 24;
32210 var durationWeek = durationDay * 7;
32211 var durationMonth = durationDay * 30;
32212 var durationYear = durationDay * 365;
32213
32214 function date$2(t) {
32215   return new Date(t);
32216 }
32217
32218 function number$3(t) {
32219   return t instanceof Date ? +t : +new Date(+t);
32220 }
32221
32222 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
32223   var scale = continuous(deinterpolateLinear, reinterpolate),
32224       invert = scale.invert,
32225       domain = scale.domain;
32226
32227   var formatMillisecond = format(".%L"),
32228       formatSecond = format(":%S"),
32229       formatMinute = format("%I:%M"),
32230       formatHour = format("%I %p"),
32231       formatDay = format("%a %d"),
32232       formatWeek = format("%b %d"),
32233       formatMonth = format("%B"),
32234       formatYear = format("%Y");
32235
32236   var tickIntervals = [
32237     [second$$1,  1,      durationSecond],
32238     [second$$1,  5,  5 * durationSecond],
32239     [second$$1, 15, 15 * durationSecond],
32240     [second$$1, 30, 30 * durationSecond],
32241     [minute$$1,  1,      durationMinute],
32242     [minute$$1,  5,  5 * durationMinute],
32243     [minute$$1, 15, 15 * durationMinute],
32244     [minute$$1, 30, 30 * durationMinute],
32245     [  hour$$1,  1,      durationHour  ],
32246     [  hour$$1,  3,  3 * durationHour  ],
32247     [  hour$$1,  6,  6 * durationHour  ],
32248     [  hour$$1, 12, 12 * durationHour  ],
32249     [   day$$1,  1,      durationDay   ],
32250     [   day$$1,  2,  2 * durationDay   ],
32251     [  week,  1,      durationWeek  ],
32252     [ month$$1,  1,      durationMonth ],
32253     [ month$$1,  3,  3 * durationMonth ],
32254     [  year$$1,  1,      durationYear  ]
32255   ];
32256
32257   function tickFormat(date) {
32258     return (second$$1(date) < date ? formatMillisecond
32259         : minute$$1(date) < date ? formatSecond
32260         : hour$$1(date) < date ? formatMinute
32261         : day$$1(date) < date ? formatHour
32262         : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
32263         : year$$1(date) < date ? formatMonth
32264         : formatYear)(date);
32265   }
32266
32267   function tickInterval(interval, start, stop, step) {
32268     if (interval == null) interval = 10;
32269
32270     // If a desired tick count is specified, pick a reasonable tick interval
32271     // based on the extent of the domain and a rough estimate of tick size.
32272     // Otherwise, assume interval is already a time interval and use it.
32273     if (typeof interval === "number") {
32274       var target = Math.abs(stop - start) / interval,
32275           i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
32276       if (i === tickIntervals.length) {
32277         step = tickStep(start / durationYear, stop / durationYear, interval);
32278         interval = year$$1;
32279       } else if (i) {
32280         i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
32281         step = i[1];
32282         interval = i[0];
32283       } else {
32284         step = tickStep(start, stop, interval);
32285         interval = millisecond$$1;
32286       }
32287     }
32288
32289     return step == null ? interval : interval.every(step);
32290   }
32291
32292   scale.invert = function(y) {
32293     return new Date(invert(y));
32294   };
32295
32296   scale.domain = function(_) {
32297     return arguments.length ? domain(map$3.call(_, number$3)) : domain().map(date$2);
32298   };
32299
32300   scale.ticks = function(interval, step) {
32301     var d = domain(),
32302         t0 = d[0],
32303         t1 = d[d.length - 1],
32304         r = t1 < t0,
32305         t;
32306     if (r) t = t0, t0 = t1, t1 = t;
32307     t = tickInterval(interval, t0, t1, step);
32308     t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
32309     return r ? t.reverse() : t;
32310   };
32311
32312   scale.tickFormat = function(count, specifier) {
32313     return specifier == null ? tickFormat : format(specifier);
32314   };
32315
32316   scale.nice = function(interval, step) {
32317     var d = domain();
32318     return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
32319         ? domain(nice(d, interval))
32320         : scale;
32321   };
32322
32323   scale.copy = function() {
32324     return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
32325   };
32326
32327   return scale;
32328 }
32329
32330 var time = function() {
32331   return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
32332 };
32333
32334 var utcTime = function() {
32335   return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
32336 };
32337
32338 var colors = function(s) {
32339   return s.match(/.{6}/g).map(function(x) {
32340     return "#" + x;
32341   });
32342 };
32343
32344 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
32345
32346 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
32347
32348 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
32349
32350 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
32351
32352 var cubehelix$5 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
32353
32354 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32355
32356 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
32357
32358 var rainbow = cubehelix();
32359
32360 var rainbow$1 = function(t) {
32361   if (t < 0 || t > 1) t -= Math.floor(t);
32362   var ts = Math.abs(t - 0.5);
32363   rainbow.h = 360 * t - 100;
32364   rainbow.s = 1.5 - 1.5 * ts;
32365   rainbow.l = 0.8 - 0.9 * ts;
32366   return rainbow + "";
32367 };
32368
32369 function ramp(range) {
32370   var n = range.length;
32371   return function(t) {
32372     return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
32373   };
32374 }
32375
32376 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
32377
32378 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
32379
32380 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
32381
32382 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
32383
32384 function sequential(interpolator) {
32385   var x0 = 0,
32386       x1 = 1,
32387       clamp = false;
32388
32389   function scale(x) {
32390     var t = (x - x0) / (x1 - x0);
32391     return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
32392   }
32393
32394   scale.domain = function(_) {
32395     return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
32396   };
32397
32398   scale.clamp = function(_) {
32399     return arguments.length ? (clamp = !!_, scale) : clamp;
32400   };
32401
32402   scale.interpolator = function(_) {
32403     return arguments.length ? (interpolator = _, scale) : interpolator;
32404   };
32405
32406   scale.copy = function() {
32407     return sequential(interpolator).domain([x0, x1]).clamp(clamp);
32408   };
32409
32410   return linearish(scale);
32411 }
32412
32413 var constant$11 = function(x) {
32414   return function constant() {
32415     return x;
32416   };
32417 };
32418
32419 var epsilon$3 = 1e-12;
32420 var pi$4 = Math.PI;
32421 var halfPi$3 = pi$4 / 2;
32422 var tau$4 = 2 * pi$4;
32423
32424 function arcInnerRadius(d) {
32425   return d.innerRadius;
32426 }
32427
32428 function arcOuterRadius(d) {
32429   return d.outerRadius;
32430 }
32431
32432 function arcStartAngle(d) {
32433   return d.startAngle;
32434 }
32435
32436 function arcEndAngle(d) {
32437   return d.endAngle;
32438 }
32439
32440 function arcPadAngle(d) {
32441   return d && d.padAngle; // Note: optional!
32442 }
32443
32444 function asin$1(x) {
32445   return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x);
32446 }
32447
32448 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
32449   var x10 = x1 - x0, y10 = y1 - y0,
32450       x32 = x3 - x2, y32 = y3 - y2,
32451       t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
32452   return [x0 + t * x10, y0 + t * y10];
32453 }
32454
32455 // Compute perpendicular offset line of length rc.
32456 // http://mathworld.wolfram.com/Circle-LineIntersection.html
32457 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
32458   var x01 = x0 - x1,
32459       y01 = y0 - y1,
32460       lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01),
32461       ox = lo * y01,
32462       oy = -lo * x01,
32463       x11 = x0 + ox,
32464       y11 = y0 + oy,
32465       x10 = x1 + ox,
32466       y10 = y1 + oy,
32467       x00 = (x11 + x10) / 2,
32468       y00 = (y11 + y10) / 2,
32469       dx = x10 - x11,
32470       dy = y10 - y11,
32471       d2 = dx * dx + dy * dy,
32472       r = r1 - rc,
32473       D = x11 * y10 - x10 * y11,
32474       d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)),
32475       cx0 = (D * dy - dx * d) / d2,
32476       cy0 = (-D * dx - dy * d) / d2,
32477       cx1 = (D * dy + dx * d) / d2,
32478       cy1 = (-D * dx + dy * d) / d2,
32479       dx0 = cx0 - x00,
32480       dy0 = cy0 - y00,
32481       dx1 = cx1 - x00,
32482       dy1 = cy1 - y00;
32483
32484   // Pick the closer of the two intersection points.
32485   // TODO Is there a faster way to determine which intersection to use?
32486   if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
32487
32488   return {
32489     cx: cx0,
32490     cy: cy0,
32491     x01: -ox,
32492     y01: -oy,
32493     x11: cx0 * (r1 / r - 1),
32494     y11: cy0 * (r1 / r - 1)
32495   };
32496 }
32497
32498 var arc = function() {
32499   var innerRadius = arcInnerRadius,
32500       outerRadius = arcOuterRadius,
32501       cornerRadius = constant$11(0),
32502       padRadius = null,
32503       startAngle = arcStartAngle,
32504       endAngle = arcEndAngle,
32505       padAngle = arcPadAngle,
32506       context = null;
32507
32508   function arc() {
32509     var buffer,
32510         r,
32511         r0 = +innerRadius.apply(this, arguments),
32512         r1 = +outerRadius.apply(this, arguments),
32513         a0 = startAngle.apply(this, arguments) - halfPi$3,
32514         a1 = endAngle.apply(this, arguments) - halfPi$3,
32515         da = Math.abs(a1 - a0),
32516         cw = a1 > a0;
32517
32518     if (!context) context = buffer = path();
32519
32520     // Ensure that the outer radius is always larger than the inner radius.
32521     if (r1 < r0) r = r1, r1 = r0, r0 = r;
32522
32523     // Is it a point?
32524     if (!(r1 > epsilon$3)) context.moveTo(0, 0);
32525
32526     // Or is it a circle or annulus?
32527     else if (da > tau$4 - epsilon$3) {
32528       context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0));
32529       context.arc(0, 0, r1, a0, a1, !cw);
32530       if (r0 > epsilon$3) {
32531         context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1));
32532         context.arc(0, 0, r0, a1, a0, cw);
32533       }
32534     }
32535
32536     // Or is it a circular or annular sector?
32537     else {
32538       var a01 = a0,
32539           a11 = a1,
32540           a00 = a0,
32541           a10 = a1,
32542           da0 = da,
32543           da1 = da,
32544           ap = padAngle.apply(this, arguments) / 2,
32545           rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)),
32546           rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
32547           rc0 = rc,
32548           rc1 = rc,
32549           t0,
32550           t1;
32551
32552       // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
32553       if (rp > epsilon$3) {
32554         var p0 = asin$1(rp / r0 * Math.sin(ap)),
32555             p1 = asin$1(rp / r1 * Math.sin(ap));
32556         if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
32557         else da0 = 0, a00 = a10 = (a0 + a1) / 2;
32558         if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
32559         else da1 = 0, a01 = a11 = (a0 + a1) / 2;
32560       }
32561
32562       var x01 = r1 * Math.cos(a01),
32563           y01 = r1 * Math.sin(a01),
32564           x10 = r0 * Math.cos(a10),
32565           y10 = r0 * Math.sin(a10);
32566
32567       // Apply rounded corners?
32568       if (rc > epsilon$3) {
32569         var x11 = r1 * Math.cos(a11),
32570             y11 = r1 * Math.sin(a11),
32571             x00 = r0 * Math.cos(a00),
32572             y00 = r0 * Math.sin(a00);
32573
32574         // Restrict the corner radius according to the sector angle.
32575         if (da < pi$4) {
32576           var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
32577               ax = x01 - oc[0],
32578               ay = y01 - oc[1],
32579               bx = x11 - oc[0],
32580               by = y11 - oc[1],
32581               kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2),
32582               lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
32583           rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
32584           rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
32585         }
32586       }
32587
32588       // Is the sector collapsed to a line?
32589       if (!(da1 > epsilon$3)) context.moveTo(x01, y01);
32590
32591       // Does the sector’s outer ring have rounded corners?
32592       else if (rc1 > epsilon$3) {
32593         t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
32594         t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
32595
32596         context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
32597
32598         // Have the corners merged?
32599         if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
32600
32601         // Otherwise, draw the two corners and the ring.
32602         else {
32603           context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
32604           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);
32605           context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
32606         }
32607       }
32608
32609       // Or is the outer ring just a circular arc?
32610       else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
32611
32612       // Is there no inner ring, and it’s a circular sector?
32613       // Or perhaps it’s an annular sector collapsed due to padding?
32614       if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10);
32615
32616       // Does the sector’s inner ring (or point) have rounded corners?
32617       else if (rc0 > epsilon$3) {
32618         t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
32619         t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
32620
32621         context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
32622
32623         // Have the corners merged?
32624         if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
32625
32626         // Otherwise, draw the two corners and the ring.
32627         else {
32628           context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
32629           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);
32630           context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
32631         }
32632       }
32633
32634       // Or is the inner ring just a circular arc?
32635       else context.arc(0, 0, r0, a10, a00, cw);
32636     }
32637
32638     context.closePath();
32639
32640     if (buffer) return context = null, buffer + "" || null;
32641   }
32642
32643   arc.centroid = function() {
32644     var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
32645         a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2;
32646     return [Math.cos(a) * r, Math.sin(a) * r];
32647   };
32648
32649   arc.innerRadius = function(_) {
32650     return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$11(+_), arc) : innerRadius;
32651   };
32652
32653   arc.outerRadius = function(_) {
32654     return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$11(+_), arc) : outerRadius;
32655   };
32656
32657   arc.cornerRadius = function(_) {
32658     return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$11(+_), arc) : cornerRadius;
32659   };
32660
32661   arc.padRadius = function(_) {
32662     return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$11(+_), arc) : padRadius;
32663   };
32664
32665   arc.startAngle = function(_) {
32666     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$11(+_), arc) : startAngle;
32667   };
32668
32669   arc.endAngle = function(_) {
32670     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$11(+_), arc) : endAngle;
32671   };
32672
32673   arc.padAngle = function(_) {
32674     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$11(+_), arc) : padAngle;
32675   };
32676
32677   arc.context = function(_) {
32678     return arguments.length ? ((context = _ == null ? null : _), arc) : context;
32679   };
32680
32681   return arc;
32682 };
32683
32684 function Linear(context) {
32685   this._context = context;
32686 }
32687
32688 Linear.prototype = {
32689   areaStart: function() {
32690     this._line = 0;
32691   },
32692   areaEnd: function() {
32693     this._line = NaN;
32694   },
32695   lineStart: function() {
32696     this._point = 0;
32697   },
32698   lineEnd: function() {
32699     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
32700     this._line = 1 - this._line;
32701   },
32702   point: function(x, y) {
32703     x = +x, y = +y;
32704     switch (this._point) {
32705       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
32706       case 1: this._point = 2; // proceed
32707       default: this._context.lineTo(x, y); break;
32708     }
32709   }
32710 };
32711
32712 var curveLinear = function(context) {
32713   return new Linear(context);
32714 };
32715
32716 function x$3(p) {
32717   return p[0];
32718 }
32719
32720 function y$3(p) {
32721   return p[1];
32722 }
32723
32724 var line = function() {
32725   var x$$1 = x$3,
32726       y$$1 = y$3,
32727       defined = constant$11(true),
32728       context = null,
32729       curve = curveLinear,
32730       output = null;
32731
32732   function line(data) {
32733     var i,
32734         n = data.length,
32735         d,
32736         defined0 = false,
32737         buffer;
32738
32739     if (context == null) output = curve(buffer = path());
32740
32741     for (i = 0; i <= n; ++i) {
32742       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32743         if (defined0 = !defined0) output.lineStart();
32744         else output.lineEnd();
32745       }
32746       if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
32747     }
32748
32749     if (buffer) return output = null, buffer + "" || null;
32750   }
32751
32752   line.x = function(_) {
32753     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), line) : x$$1;
32754   };
32755
32756   line.y = function(_) {
32757     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), line) : y$$1;
32758   };
32759
32760   line.defined = function(_) {
32761     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$11(!!_), line) : defined;
32762   };
32763
32764   line.curve = function(_) {
32765     return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
32766   };
32767
32768   line.context = function(_) {
32769     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
32770   };
32771
32772   return line;
32773 };
32774
32775 var area$1 = function() {
32776   var x0 = x$3,
32777       x1 = null,
32778       y0 = constant$11(0),
32779       y1 = y$3,
32780       defined = constant$11(true),
32781       context = null,
32782       curve = curveLinear,
32783       output = null;
32784
32785   function area(data) {
32786     var i,
32787         j,
32788         k,
32789         n = data.length,
32790         d,
32791         defined0 = false,
32792         buffer,
32793         x0z = new Array(n),
32794         y0z = new Array(n);
32795
32796     if (context == null) output = curve(buffer = path());
32797
32798     for (i = 0; i <= n; ++i) {
32799       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
32800         if (defined0 = !defined0) {
32801           j = i;
32802           output.areaStart();
32803           output.lineStart();
32804         } else {
32805           output.lineEnd();
32806           output.lineStart();
32807           for (k = i - 1; k >= j; --k) {
32808             output.point(x0z[k], y0z[k]);
32809           }
32810           output.lineEnd();
32811           output.areaEnd();
32812         }
32813       }
32814       if (defined0) {
32815         x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
32816         output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
32817       }
32818     }
32819
32820     if (buffer) return output = null, buffer + "" || null;
32821   }
32822
32823   function arealine() {
32824     return line().defined(defined).curve(curve).context(context);
32825   }
32826
32827   area.x = function(_) {
32828     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$11(+_), x1 = null, area) : x0;
32829   };
32830
32831   area.x0 = function(_) {
32832     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$11(+_), area) : x0;
32833   };
32834
32835   area.x1 = function(_) {
32836     return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$11(+_), area) : x1;
32837   };
32838
32839   area.y = function(_) {
32840     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$11(+_), y1 = null, area) : y0;
32841   };
32842
32843   area.y0 = function(_) {
32844     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$11(+_), area) : y0;
32845   };
32846
32847   area.y1 = function(_) {
32848     return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$11(+_), area) : y1;
32849   };
32850
32851   area.lineX0 =
32852   area.lineY0 = function() {
32853     return arealine().x(x0).y(y0);
32854   };
32855
32856   area.lineY1 = function() {
32857     return arealine().x(x0).y(y1);
32858   };
32859
32860   area.lineX1 = function() {
32861     return arealine().x(x1).y(y0);
32862   };
32863
32864   area.defined = function(_) {
32865     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$11(!!_), area) : defined;
32866   };
32867
32868   area.curve = function(_) {
32869     return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
32870   };
32871
32872   area.context = function(_) {
32873     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
32874   };
32875
32876   return area;
32877 };
32878
32879 var descending$1 = function(a, b) {
32880   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
32881 };
32882
32883 var identity$8 = function(d) {
32884   return d;
32885 };
32886
32887 var pie = function() {
32888   var value = identity$8,
32889       sortValues = descending$1,
32890       sort = null,
32891       startAngle = constant$11(0),
32892       endAngle = constant$11(tau$4),
32893       padAngle = constant$11(0);
32894
32895   function pie(data) {
32896     var i,
32897         n = data.length,
32898         j,
32899         k,
32900         sum = 0,
32901         index = new Array(n),
32902         arcs = new Array(n),
32903         a0 = +startAngle.apply(this, arguments),
32904         da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)),
32905         a1,
32906         p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
32907         pa = p * (da < 0 ? -1 : 1),
32908         v;
32909
32910     for (i = 0; i < n; ++i) {
32911       if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
32912         sum += v;
32913       }
32914     }
32915
32916     // Optionally sort the arcs by previously-computed values or by data.
32917     if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
32918     else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
32919
32920     // Compute the arcs! They are stored in the original data's order.
32921     for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
32922       j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
32923         data: data[j],
32924         index: i,
32925         value: v,
32926         startAngle: a0,
32927         endAngle: a1,
32928         padAngle: p
32929       };
32930     }
32931
32932     return arcs;
32933   }
32934
32935   pie.value = function(_) {
32936     return arguments.length ? (value = typeof _ === "function" ? _ : constant$11(+_), pie) : value;
32937   };
32938
32939   pie.sortValues = function(_) {
32940     return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
32941   };
32942
32943   pie.sort = function(_) {
32944     return arguments.length ? (sort = _, sortValues = null, pie) : sort;
32945   };
32946
32947   pie.startAngle = function(_) {
32948     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$11(+_), pie) : startAngle;
32949   };
32950
32951   pie.endAngle = function(_) {
32952     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$11(+_), pie) : endAngle;
32953   };
32954
32955   pie.padAngle = function(_) {
32956     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$11(+_), pie) : padAngle;
32957   };
32958
32959   return pie;
32960 };
32961
32962 var curveRadialLinear = curveRadial(curveLinear);
32963
32964 function Radial(curve) {
32965   this._curve = curve;
32966 }
32967
32968 Radial.prototype = {
32969   areaStart: function() {
32970     this._curve.areaStart();
32971   },
32972   areaEnd: function() {
32973     this._curve.areaEnd();
32974   },
32975   lineStart: function() {
32976     this._curve.lineStart();
32977   },
32978   lineEnd: function() {
32979     this._curve.lineEnd();
32980   },
32981   point: function(a, r) {
32982     this._curve.point(r * Math.sin(a), r * -Math.cos(a));
32983   }
32984 };
32985
32986 function curveRadial(curve) {
32987
32988   function radial(context) {
32989     return new Radial(curve(context));
32990   }
32991
32992   radial._curve = curve;
32993
32994   return radial;
32995 }
32996
32997 function radialLine(l) {
32998   var c = l.curve;
32999
33000   l.angle = l.x, delete l.x;
33001   l.radius = l.y, delete l.y;
33002
33003   l.curve = function(_) {
33004     return arguments.length ? c(curveRadial(_)) : c()._curve;
33005   };
33006
33007   return l;
33008 }
33009
33010 var radialLine$1 = function() {
33011   return radialLine(line().curve(curveRadialLinear));
33012 };
33013
33014 var radialArea = function() {
33015   var a = area$1().curve(curveRadialLinear),
33016       c = a.curve,
33017       x0 = a.lineX0,
33018       x1 = a.lineX1,
33019       y0 = a.lineY0,
33020       y1 = a.lineY1;
33021
33022   a.angle = a.x, delete a.x;
33023   a.startAngle = a.x0, delete a.x0;
33024   a.endAngle = a.x1, delete a.x1;
33025   a.radius = a.y, delete a.y;
33026   a.innerRadius = a.y0, delete a.y0;
33027   a.outerRadius = a.y1, delete a.y1;
33028   a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
33029   a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
33030   a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
33031   a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
33032
33033   a.curve = function(_) {
33034     return arguments.length ? c(curveRadial(_)) : c()._curve;
33035   };
33036
33037   return a;
33038 };
33039
33040 var circle$2 = {
33041   draw: function(context, size) {
33042     var r = Math.sqrt(size / pi$4);
33043     context.moveTo(r, 0);
33044     context.arc(0, 0, r, 0, tau$4);
33045   }
33046 };
33047
33048 var cross$1 = {
33049   draw: function(context, size) {
33050     var r = Math.sqrt(size / 5) / 2;
33051     context.moveTo(-3 * r, -r);
33052     context.lineTo(-r, -r);
33053     context.lineTo(-r, -3 * r);
33054     context.lineTo(r, -3 * r);
33055     context.lineTo(r, -r);
33056     context.lineTo(3 * r, -r);
33057     context.lineTo(3 * r, r);
33058     context.lineTo(r, r);
33059     context.lineTo(r, 3 * r);
33060     context.lineTo(-r, 3 * r);
33061     context.lineTo(-r, r);
33062     context.lineTo(-3 * r, r);
33063     context.closePath();
33064   }
33065 };
33066
33067 var tan30 = Math.sqrt(1 / 3);
33068 var tan30_2 = tan30 * 2;
33069
33070 var diamond = {
33071   draw: function(context, size) {
33072     var y = Math.sqrt(size / tan30_2),
33073         x = y * tan30;
33074     context.moveTo(0, -y);
33075     context.lineTo(x, 0);
33076     context.lineTo(0, y);
33077     context.lineTo(-x, 0);
33078     context.closePath();
33079   }
33080 };
33081
33082 var ka = 0.89081309152928522810;
33083 var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10);
33084 var kx = Math.sin(tau$4 / 10) * kr;
33085 var ky = -Math.cos(tau$4 / 10) * kr;
33086
33087 var star = {
33088   draw: function(context, size) {
33089     var r = Math.sqrt(size * ka),
33090         x = kx * r,
33091         y = ky * r;
33092     context.moveTo(0, -r);
33093     context.lineTo(x, y);
33094     for (var i = 1; i < 5; ++i) {
33095       var a = tau$4 * i / 5,
33096           c = Math.cos(a),
33097           s = Math.sin(a);
33098       context.lineTo(s * r, -c * r);
33099       context.lineTo(c * x - s * y, s * x + c * y);
33100     }
33101     context.closePath();
33102   }
33103 };
33104
33105 var square = {
33106   draw: function(context, size) {
33107     var w = Math.sqrt(size),
33108         x = -w / 2;
33109     context.rect(x, x, w, w);
33110   }
33111 };
33112
33113 var sqrt3 = Math.sqrt(3);
33114
33115 var triangle = {
33116   draw: function(context, size) {
33117     var y = -Math.sqrt(size / (sqrt3 * 3));
33118     context.moveTo(0, y * 2);
33119     context.lineTo(-sqrt3 * y, -y);
33120     context.lineTo(sqrt3 * y, -y);
33121     context.closePath();
33122   }
33123 };
33124
33125 var c = -0.5;
33126 var s = Math.sqrt(3) / 2;
33127 var k = 1 / Math.sqrt(12);
33128 var a = (k / 2 + 1) * 3;
33129
33130 var wye = {
33131   draw: function(context, size) {
33132     var r = Math.sqrt(size / a),
33133         x0 = r / 2,
33134         y0 = r * k,
33135         x1 = x0,
33136         y1 = r * k + r,
33137         x2 = -x1,
33138         y2 = y1;
33139     context.moveTo(x0, y0);
33140     context.lineTo(x1, y1);
33141     context.lineTo(x2, y2);
33142     context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
33143     context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
33144     context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
33145     context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
33146     context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
33147     context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
33148     context.closePath();
33149   }
33150 };
33151
33152 var symbols = [
33153   circle$2,
33154   cross$1,
33155   diamond,
33156   square,
33157   star,
33158   triangle,
33159   wye
33160 ];
33161
33162 var symbol = function() {
33163   var type = constant$11(circle$2),
33164       size = constant$11(64),
33165       context = null;
33166
33167   function symbol() {
33168     var buffer;
33169     if (!context) context = buffer = path();
33170     type.apply(this, arguments).draw(context, +size.apply(this, arguments));
33171     if (buffer) return context = null, buffer + "" || null;
33172   }
33173
33174   symbol.type = function(_) {
33175     return arguments.length ? (type = typeof _ === "function" ? _ : constant$11(_), symbol) : type;
33176   };
33177
33178   symbol.size = function(_) {
33179     return arguments.length ? (size = typeof _ === "function" ? _ : constant$11(+_), symbol) : size;
33180   };
33181
33182   symbol.context = function(_) {
33183     return arguments.length ? (context = _ == null ? null : _, symbol) : context;
33184   };
33185
33186   return symbol;
33187 };
33188
33189 var noop$2 = function() {};
33190
33191 function point$2(that, x, y) {
33192   that._context.bezierCurveTo(
33193     (2 * that._x0 + that._x1) / 3,
33194     (2 * that._y0 + that._y1) / 3,
33195     (that._x0 + 2 * that._x1) / 3,
33196     (that._y0 + 2 * that._y1) / 3,
33197     (that._x0 + 4 * that._x1 + x) / 6,
33198     (that._y0 + 4 * that._y1 + y) / 6
33199   );
33200 }
33201
33202 function Basis(context) {
33203   this._context = context;
33204 }
33205
33206 Basis.prototype = {
33207   areaStart: function() {
33208     this._line = 0;
33209   },
33210   areaEnd: function() {
33211     this._line = NaN;
33212   },
33213   lineStart: function() {
33214     this._x0 = this._x1 =
33215     this._y0 = this._y1 = NaN;
33216     this._point = 0;
33217   },
33218   lineEnd: function() {
33219     switch (this._point) {
33220       case 3: point$2(this, this._x1, this._y1); // proceed
33221       case 2: this._context.lineTo(this._x1, this._y1); break;
33222     }
33223     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33224     this._line = 1 - this._line;
33225   },
33226   point: function(x, y) {
33227     x = +x, y = +y;
33228     switch (this._point) {
33229       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33230       case 1: this._point = 2; break;
33231       case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
33232       default: point$2(this, x, y); break;
33233     }
33234     this._x0 = this._x1, this._x1 = x;
33235     this._y0 = this._y1, this._y1 = y;
33236   }
33237 };
33238
33239 var basis$4 = function(context) {
33240   return new Basis(context);
33241 };
33242
33243 function BasisClosed(context) {
33244   this._context = context;
33245 }
33246
33247 BasisClosed.prototype = {
33248   areaStart: noop$2,
33249   areaEnd: noop$2,
33250   lineStart: function() {
33251     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
33252     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
33253     this._point = 0;
33254   },
33255   lineEnd: function() {
33256     switch (this._point) {
33257       case 1: {
33258         this._context.moveTo(this._x2, this._y2);
33259         this._context.closePath();
33260         break;
33261       }
33262       case 2: {
33263         this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
33264         this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
33265         this._context.closePath();
33266         break;
33267       }
33268       case 3: {
33269         this.point(this._x2, this._y2);
33270         this.point(this._x3, this._y3);
33271         this.point(this._x4, this._y4);
33272         break;
33273       }
33274     }
33275   },
33276   point: function(x, y) {
33277     x = +x, y = +y;
33278     switch (this._point) {
33279       case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
33280       case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
33281       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;
33282       default: point$2(this, x, y); break;
33283     }
33284     this._x0 = this._x1, this._x1 = x;
33285     this._y0 = this._y1, this._y1 = y;
33286   }
33287 };
33288
33289 var basisClosed$2 = function(context) {
33290   return new BasisClosed(context);
33291 };
33292
33293 function BasisOpen(context) {
33294   this._context = context;
33295 }
33296
33297 BasisOpen.prototype = {
33298   areaStart: function() {
33299     this._line = 0;
33300   },
33301   areaEnd: function() {
33302     this._line = NaN;
33303   },
33304   lineStart: function() {
33305     this._x0 = this._x1 =
33306     this._y0 = this._y1 = NaN;
33307     this._point = 0;
33308   },
33309   lineEnd: function() {
33310     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33311     this._line = 1 - this._line;
33312   },
33313   point: function(x, y) {
33314     x = +x, y = +y;
33315     switch (this._point) {
33316       case 0: this._point = 1; break;
33317       case 1: this._point = 2; break;
33318       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;
33319       case 3: this._point = 4; // proceed
33320       default: point$2(this, x, y); break;
33321     }
33322     this._x0 = this._x1, this._x1 = x;
33323     this._y0 = this._y1, this._y1 = y;
33324   }
33325 };
33326
33327 var basisOpen = function(context) {
33328   return new BasisOpen(context);
33329 };
33330
33331 function Bundle(context, beta) {
33332   this._basis = new Basis(context);
33333   this._beta = beta;
33334 }
33335
33336 Bundle.prototype = {
33337   lineStart: function() {
33338     this._x = [];
33339     this._y = [];
33340     this._basis.lineStart();
33341   },
33342   lineEnd: function() {
33343     var x = this._x,
33344         y = this._y,
33345         j = x.length - 1;
33346
33347     if (j > 0) {
33348       var x0 = x[0],
33349           y0 = y[0],
33350           dx = x[j] - x0,
33351           dy = y[j] - y0,
33352           i = -1,
33353           t;
33354
33355       while (++i <= j) {
33356         t = i / j;
33357         this._basis.point(
33358           this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
33359           this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
33360         );
33361       }
33362     }
33363
33364     this._x = this._y = null;
33365     this._basis.lineEnd();
33366   },
33367   point: function(x, y) {
33368     this._x.push(+x);
33369     this._y.push(+y);
33370   }
33371 };
33372
33373 var bundle = ((function custom(beta) {
33374
33375   function bundle(context) {
33376     return beta === 1 ? new Basis(context) : new Bundle(context, beta);
33377   }
33378
33379   bundle.beta = function(beta) {
33380     return custom(+beta);
33381   };
33382
33383   return bundle;
33384 }))(0.85);
33385
33386 function point$3(that, x, y) {
33387   that._context.bezierCurveTo(
33388     that._x1 + that._k * (that._x2 - that._x0),
33389     that._y1 + that._k * (that._y2 - that._y0),
33390     that._x2 + that._k * (that._x1 - x),
33391     that._y2 + that._k * (that._y1 - y),
33392     that._x2,
33393     that._y2
33394   );
33395 }
33396
33397 function Cardinal(context, tension) {
33398   this._context = context;
33399   this._k = (1 - tension) / 6;
33400 }
33401
33402 Cardinal.prototype = {
33403   areaStart: function() {
33404     this._line = 0;
33405   },
33406   areaEnd: function() {
33407     this._line = NaN;
33408   },
33409   lineStart: function() {
33410     this._x0 = this._x1 = this._x2 =
33411     this._y0 = this._y1 = this._y2 = NaN;
33412     this._point = 0;
33413   },
33414   lineEnd: function() {
33415     switch (this._point) {
33416       case 2: this._context.lineTo(this._x2, this._y2); break;
33417       case 3: point$3(this, this._x1, this._y1); break;
33418     }
33419     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33420     this._line = 1 - this._line;
33421   },
33422   point: function(x, y) {
33423     x = +x, y = +y;
33424     switch (this._point) {
33425       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33426       case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
33427       case 2: this._point = 3; // proceed
33428       default: point$3(this, x, y); break;
33429     }
33430     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33431     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33432   }
33433 };
33434
33435 var cardinal = ((function custom(tension) {
33436
33437   function cardinal(context) {
33438     return new Cardinal(context, tension);
33439   }
33440
33441   cardinal.tension = function(tension) {
33442     return custom(+tension);
33443   };
33444
33445   return cardinal;
33446 }))(0);
33447
33448 function CardinalClosed(context, tension) {
33449   this._context = context;
33450   this._k = (1 - tension) / 6;
33451 }
33452
33453 CardinalClosed.prototype = {
33454   areaStart: noop$2,
33455   areaEnd: noop$2,
33456   lineStart: function() {
33457     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33458     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33459     this._point = 0;
33460   },
33461   lineEnd: function() {
33462     switch (this._point) {
33463       case 1: {
33464         this._context.moveTo(this._x3, this._y3);
33465         this._context.closePath();
33466         break;
33467       }
33468       case 2: {
33469         this._context.lineTo(this._x3, this._y3);
33470         this._context.closePath();
33471         break;
33472       }
33473       case 3: {
33474         this.point(this._x3, this._y3);
33475         this.point(this._x4, this._y4);
33476         this.point(this._x5, this._y5);
33477         break;
33478       }
33479     }
33480   },
33481   point: function(x, y) {
33482     x = +x, y = +y;
33483     switch (this._point) {
33484       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33485       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33486       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33487       default: point$3(this, x, y); break;
33488     }
33489     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33490     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33491   }
33492 };
33493
33494 var cardinalClosed = ((function custom(tension) {
33495
33496   function cardinal(context) {
33497     return new CardinalClosed(context, tension);
33498   }
33499
33500   cardinal.tension = function(tension) {
33501     return custom(+tension);
33502   };
33503
33504   return cardinal;
33505 }))(0);
33506
33507 function CardinalOpen(context, tension) {
33508   this._context = context;
33509   this._k = (1 - tension) / 6;
33510 }
33511
33512 CardinalOpen.prototype = {
33513   areaStart: function() {
33514     this._line = 0;
33515   },
33516   areaEnd: function() {
33517     this._line = NaN;
33518   },
33519   lineStart: function() {
33520     this._x0 = this._x1 = this._x2 =
33521     this._y0 = this._y1 = this._y2 = NaN;
33522     this._point = 0;
33523   },
33524   lineEnd: function() {
33525     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33526     this._line = 1 - this._line;
33527   },
33528   point: function(x, y) {
33529     x = +x, y = +y;
33530     switch (this._point) {
33531       case 0: this._point = 1; break;
33532       case 1: this._point = 2; break;
33533       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33534       case 3: this._point = 4; // proceed
33535       default: point$3(this, x, y); break;
33536     }
33537     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33538     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33539   }
33540 };
33541
33542 var cardinalOpen = ((function custom(tension) {
33543
33544   function cardinal(context) {
33545     return new CardinalOpen(context, tension);
33546   }
33547
33548   cardinal.tension = function(tension) {
33549     return custom(+tension);
33550   };
33551
33552   return cardinal;
33553 }))(0);
33554
33555 function point$4(that, x, y) {
33556   var x1 = that._x1,
33557       y1 = that._y1,
33558       x2 = that._x2,
33559       y2 = that._y2;
33560
33561   if (that._l01_a > epsilon$3) {
33562     var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
33563         n = 3 * that._l01_a * (that._l01_a + that._l12_a);
33564     x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
33565     y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
33566   }
33567
33568   if (that._l23_a > epsilon$3) {
33569     var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
33570         m = 3 * that._l23_a * (that._l23_a + that._l12_a);
33571     x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
33572     y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
33573   }
33574
33575   that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
33576 }
33577
33578 function CatmullRom(context, alpha) {
33579   this._context = context;
33580   this._alpha = alpha;
33581 }
33582
33583 CatmullRom.prototype = {
33584   areaStart: function() {
33585     this._line = 0;
33586   },
33587   areaEnd: function() {
33588     this._line = NaN;
33589   },
33590   lineStart: function() {
33591     this._x0 = this._x1 = this._x2 =
33592     this._y0 = this._y1 = this._y2 = NaN;
33593     this._l01_a = this._l12_a = this._l23_a =
33594     this._l01_2a = this._l12_2a = this._l23_2a =
33595     this._point = 0;
33596   },
33597   lineEnd: function() {
33598     switch (this._point) {
33599       case 2: this._context.lineTo(this._x2, this._y2); break;
33600       case 3: this.point(this._x2, this._y2); break;
33601     }
33602     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33603     this._line = 1 - this._line;
33604   },
33605   point: function(x, y) {
33606     x = +x, y = +y;
33607
33608     if (this._point) {
33609       var x23 = this._x2 - x,
33610           y23 = this._y2 - y;
33611       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33612     }
33613
33614     switch (this._point) {
33615       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33616       case 1: this._point = 2; break;
33617       case 2: this._point = 3; // proceed
33618       default: point$4(this, x, y); break;
33619     }
33620
33621     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33622     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33623     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33624     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33625   }
33626 };
33627
33628 var catmullRom = ((function custom(alpha) {
33629
33630   function catmullRom(context) {
33631     return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
33632   }
33633
33634   catmullRom.alpha = function(alpha) {
33635     return custom(+alpha);
33636   };
33637
33638   return catmullRom;
33639 }))(0.5);
33640
33641 function CatmullRomClosed(context, alpha) {
33642   this._context = context;
33643   this._alpha = alpha;
33644 }
33645
33646 CatmullRomClosed.prototype = {
33647   areaStart: noop$2,
33648   areaEnd: noop$2,
33649   lineStart: function() {
33650     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
33651     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
33652     this._l01_a = this._l12_a = this._l23_a =
33653     this._l01_2a = this._l12_2a = this._l23_2a =
33654     this._point = 0;
33655   },
33656   lineEnd: function() {
33657     switch (this._point) {
33658       case 1: {
33659         this._context.moveTo(this._x3, this._y3);
33660         this._context.closePath();
33661         break;
33662       }
33663       case 2: {
33664         this._context.lineTo(this._x3, this._y3);
33665         this._context.closePath();
33666         break;
33667       }
33668       case 3: {
33669         this.point(this._x3, this._y3);
33670         this.point(this._x4, this._y4);
33671         this.point(this._x5, this._y5);
33672         break;
33673       }
33674     }
33675   },
33676   point: function(x, y) {
33677     x = +x, y = +y;
33678
33679     if (this._point) {
33680       var x23 = this._x2 - x,
33681           y23 = this._y2 - y;
33682       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33683     }
33684
33685     switch (this._point) {
33686       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
33687       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
33688       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
33689       default: point$4(this, x, y); break;
33690     }
33691
33692     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33693     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33694     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33695     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33696   }
33697 };
33698
33699 var catmullRomClosed = ((function custom(alpha) {
33700
33701   function catmullRom(context) {
33702     return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
33703   }
33704
33705   catmullRom.alpha = function(alpha) {
33706     return custom(+alpha);
33707   };
33708
33709   return catmullRom;
33710 }))(0.5);
33711
33712 function CatmullRomOpen(context, alpha) {
33713   this._context = context;
33714   this._alpha = alpha;
33715 }
33716
33717 CatmullRomOpen.prototype = {
33718   areaStart: function() {
33719     this._line = 0;
33720   },
33721   areaEnd: function() {
33722     this._line = NaN;
33723   },
33724   lineStart: function() {
33725     this._x0 = this._x1 = this._x2 =
33726     this._y0 = this._y1 = this._y2 = NaN;
33727     this._l01_a = this._l12_a = this._l23_a =
33728     this._l01_2a = this._l12_2a = this._l23_2a =
33729     this._point = 0;
33730   },
33731   lineEnd: function() {
33732     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
33733     this._line = 1 - this._line;
33734   },
33735   point: function(x, y) {
33736     x = +x, y = +y;
33737
33738     if (this._point) {
33739       var x23 = this._x2 - x,
33740           y23 = this._y2 - y;
33741       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
33742     }
33743
33744     switch (this._point) {
33745       case 0: this._point = 1; break;
33746       case 1: this._point = 2; break;
33747       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
33748       case 3: this._point = 4; // proceed
33749       default: point$4(this, x, y); break;
33750     }
33751
33752     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
33753     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
33754     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
33755     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
33756   }
33757 };
33758
33759 var catmullRomOpen = ((function custom(alpha) {
33760
33761   function catmullRom(context) {
33762     return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
33763   }
33764
33765   catmullRom.alpha = function(alpha) {
33766     return custom(+alpha);
33767   };
33768
33769   return catmullRom;
33770 }))(0.5);
33771
33772 function LinearClosed(context) {
33773   this._context = context;
33774 }
33775
33776 LinearClosed.prototype = {
33777   areaStart: noop$2,
33778   areaEnd: noop$2,
33779   lineStart: function() {
33780     this._point = 0;
33781   },
33782   lineEnd: function() {
33783     if (this._point) this._context.closePath();
33784   },
33785   point: function(x, y) {
33786     x = +x, y = +y;
33787     if (this._point) this._context.lineTo(x, y);
33788     else this._point = 1, this._context.moveTo(x, y);
33789   }
33790 };
33791
33792 var linearClosed = function(context) {
33793   return new LinearClosed(context);
33794 };
33795
33796 function sign$1(x) {
33797   return x < 0 ? -1 : 1;
33798 }
33799
33800 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
33801 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
33802 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
33803 // NOV(II), P. 443, 1990.
33804 function slope3(that, x2, y2) {
33805   var h0 = that._x1 - that._x0,
33806       h1 = x2 - that._x1,
33807       s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
33808       s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
33809       p = (s0 * h1 + s1 * h0) / (h0 + h1);
33810   return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
33811 }
33812
33813 // Calculate a one-sided slope.
33814 function slope2(that, t) {
33815   var h = that._x1 - that._x0;
33816   return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
33817 }
33818
33819 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
33820 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
33821 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
33822 function point$5(that, t0, t1) {
33823   var x0 = that._x0,
33824       y0 = that._y0,
33825       x1 = that._x1,
33826       y1 = that._y1,
33827       dx = (x1 - x0) / 3;
33828   that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
33829 }
33830
33831 function MonotoneX(context) {
33832   this._context = context;
33833 }
33834
33835 MonotoneX.prototype = {
33836   areaStart: function() {
33837     this._line = 0;
33838   },
33839   areaEnd: function() {
33840     this._line = NaN;
33841   },
33842   lineStart: function() {
33843     this._x0 = this._x1 =
33844     this._y0 = this._y1 =
33845     this._t0 = NaN;
33846     this._point = 0;
33847   },
33848   lineEnd: function() {
33849     switch (this._point) {
33850       case 2: this._context.lineTo(this._x1, this._y1); break;
33851       case 3: point$5(this, this._t0, slope2(this, this._t0)); break;
33852     }
33853     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33854     this._line = 1 - this._line;
33855   },
33856   point: function(x, y) {
33857     var t1 = NaN;
33858
33859     x = +x, y = +y;
33860     if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
33861     switch (this._point) {
33862       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33863       case 1: this._point = 2; break;
33864       case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
33865       default: point$5(this, this._t0, t1 = slope3(this, x, y)); break;
33866     }
33867
33868     this._x0 = this._x1, this._x1 = x;
33869     this._y0 = this._y1, this._y1 = y;
33870     this._t0 = t1;
33871   }
33872 };
33873
33874 function MonotoneY(context) {
33875   this._context = new ReflectContext(context);
33876 }
33877
33878 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
33879   MonotoneX.prototype.point.call(this, y, x);
33880 };
33881
33882 function ReflectContext(context) {
33883   this._context = context;
33884 }
33885
33886 ReflectContext.prototype = {
33887   moveTo: function(x, y) { this._context.moveTo(y, x); },
33888   closePath: function() { this._context.closePath(); },
33889   lineTo: function(x, y) { this._context.lineTo(y, x); },
33890   bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
33891 };
33892
33893 function monotoneX(context) {
33894   return new MonotoneX(context);
33895 }
33896
33897 function monotoneY(context) {
33898   return new MonotoneY(context);
33899 }
33900
33901 function Natural(context) {
33902   this._context = context;
33903 }
33904
33905 Natural.prototype = {
33906   areaStart: function() {
33907     this._line = 0;
33908   },
33909   areaEnd: function() {
33910     this._line = NaN;
33911   },
33912   lineStart: function() {
33913     this._x = [];
33914     this._y = [];
33915   },
33916   lineEnd: function() {
33917     var x = this._x,
33918         y = this._y,
33919         n = x.length;
33920
33921     if (n) {
33922       this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
33923       if (n === 2) {
33924         this._context.lineTo(x[1], y[1]);
33925       } else {
33926         var px = controlPoints(x),
33927             py = controlPoints(y);
33928         for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
33929           this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
33930         }
33931       }
33932     }
33933
33934     if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
33935     this._line = 1 - this._line;
33936     this._x = this._y = null;
33937   },
33938   point: function(x, y) {
33939     this._x.push(+x);
33940     this._y.push(+y);
33941   }
33942 };
33943
33944 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
33945 function controlPoints(x) {
33946   var i,
33947       n = x.length - 1,
33948       m,
33949       a = new Array(n),
33950       b = new Array(n),
33951       r = new Array(n);
33952   a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
33953   for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
33954   a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
33955   for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
33956   a[n - 1] = r[n - 1] / b[n - 1];
33957   for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
33958   b[n - 1] = (x[n] + a[n - 1]) / 2;
33959   for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
33960   return [a, b];
33961 }
33962
33963 var natural = function(context) {
33964   return new Natural(context);
33965 };
33966
33967 function Step(context, t) {
33968   this._context = context;
33969   this._t = t;
33970 }
33971
33972 Step.prototype = {
33973   areaStart: function() {
33974     this._line = 0;
33975   },
33976   areaEnd: function() {
33977     this._line = NaN;
33978   },
33979   lineStart: function() {
33980     this._x = this._y = NaN;
33981     this._point = 0;
33982   },
33983   lineEnd: function() {
33984     if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
33985     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
33986     if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
33987   },
33988   point: function(x, y) {
33989     x = +x, y = +y;
33990     switch (this._point) {
33991       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
33992       case 1: this._point = 2; // proceed
33993       default: {
33994         if (this._t <= 0) {
33995           this._context.lineTo(this._x, y);
33996           this._context.lineTo(x, y);
33997         } else {
33998           var x1 = this._x * (1 - this._t) + x * this._t;
33999           this._context.lineTo(x1, this._y);
34000           this._context.lineTo(x1, y);
34001         }
34002         break;
34003       }
34004     }
34005     this._x = x, this._y = y;
34006   }
34007 };
34008
34009 var step = function(context) {
34010   return new Step(context, 0.5);
34011 };
34012
34013 function stepBefore(context) {
34014   return new Step(context, 0);
34015 }
34016
34017 function stepAfter(context) {
34018   return new Step(context, 1);
34019 }
34020
34021 var slice$5 = Array.prototype.slice;
34022
34023 var none$1 = function(series, order) {
34024   if (!((n = series.length) > 1)) return;
34025   for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
34026     s0 = s1, s1 = series[order[i]];
34027     for (var j = 0; j < m; ++j) {
34028       s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
34029     }
34030   }
34031 };
34032
34033 var none$2 = function(series) {
34034   var n = series.length, o = new Array(n);
34035   while (--n >= 0) o[n] = n;
34036   return o;
34037 };
34038
34039 function stackValue(d, key) {
34040   return d[key];
34041 }
34042
34043 var stack = function() {
34044   var keys = constant$11([]),
34045       order = none$2,
34046       offset = none$1,
34047       value = stackValue;
34048
34049   function stack(data) {
34050     var kz = keys.apply(this, arguments),
34051         i,
34052         m = data.length,
34053         n = kz.length,
34054         sz = new Array(n),
34055         oz;
34056
34057     for (i = 0; i < n; ++i) {
34058       for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
34059         si[j] = sij = [0, +value(data[j], ki, j, data)];
34060         sij.data = data[j];
34061       }
34062       si.key = ki;
34063     }
34064
34065     for (i = 0, oz = order(sz); i < n; ++i) {
34066       sz[oz[i]].index = i;
34067     }
34068
34069     offset(sz, oz);
34070     return sz;
34071   }
34072
34073   stack.keys = function(_) {
34074     return arguments.length ? (keys = typeof _ === "function" ? _ : constant$11(slice$5.call(_)), stack) : keys;
34075   };
34076
34077   stack.value = function(_) {
34078     return arguments.length ? (value = typeof _ === "function" ? _ : constant$11(+_), stack) : value;
34079   };
34080
34081   stack.order = function(_) {
34082     return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$11(slice$5.call(_)), stack) : order;
34083   };
34084
34085   stack.offset = function(_) {
34086     return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset;
34087   };
34088
34089   return stack;
34090 };
34091
34092 var expand = function(series, order) {
34093   if (!((n = series.length) > 0)) return;
34094   for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
34095     for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
34096     if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
34097   }
34098   none$1(series, order);
34099 };
34100
34101 var silhouette = function(series, order) {
34102   if (!((n = series.length) > 0)) return;
34103   for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
34104     for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
34105     s0[j][1] += s0[j][0] = -y / 2;
34106   }
34107   none$1(series, order);
34108 };
34109
34110 var wiggle = function(series, order) {
34111   if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
34112   for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
34113     for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
34114       var si = series[order[i]],
34115           sij0 = si[j][1] || 0,
34116           sij1 = si[j - 1][1] || 0,
34117           s3 = (sij0 - sij1) / 2;
34118       for (var k = 0; k < i; ++k) {
34119         var sk = series[order[k]],
34120             skj0 = sk[j][1] || 0,
34121             skj1 = sk[j - 1][1] || 0;
34122         s3 += skj0 - skj1;
34123       }
34124       s1 += sij0, s2 += s3 * sij0;
34125     }
34126     s0[j - 1][1] += s0[j - 1][0] = y;
34127     if (s1) y -= s2 / s1;
34128   }
34129   s0[j - 1][1] += s0[j - 1][0] = y;
34130   none$1(series, order);
34131 };
34132
34133 var ascending$2 = function(series) {
34134   var sums = series.map(sum$2);
34135   return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; });
34136 };
34137
34138 function sum$2(series) {
34139   var s = 0, i = -1, n = series.length, v;
34140   while (++i < n) if (v = +series[i][1]) s += v;
34141   return s;
34142 }
34143
34144 var descending$2 = function(series) {
34145   return ascending$2(series).reverse();
34146 };
34147
34148 var insideOut = function(series) {
34149   var n = series.length,
34150       i,
34151       j,
34152       sums = series.map(sum$2),
34153       order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }),
34154       top = 0,
34155       bottom = 0,
34156       tops = [],
34157       bottoms = [];
34158
34159   for (i = 0; i < n; ++i) {
34160     j = order[i];
34161     if (top < bottom) {
34162       top += sums[j];
34163       tops.push(j);
34164     } else {
34165       bottom += sums[j];
34166       bottoms.push(j);
34167     }
34168   }
34169
34170   return bottoms.reverse().concat(tops);
34171 };
34172
34173 var reverse = function(series) {
34174   return none$2(series).reverse();
34175 };
34176
34177 var frame$1 = 0;
34178 var timeout$2 = 0;
34179 var interval$2 = 0;
34180 var pokeDelay$1 = 1000;
34181 var taskHead$1;
34182 var taskTail$1;
34183 var clockLast$1 = 0;
34184 var clockNow$1 = 0;
34185 var clockSkew$1 = 0;
34186 var clock$1 = typeof performance === "object" && performance.now ? performance : Date;
34187 var setFrame$1 = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
34188
34189 function now$1() {
34190   return clockNow$1 || (setFrame$1(clearNow$1), clockNow$1 = clock$1.now() + clockSkew$1);
34191 }
34192
34193 function clearNow$1() {
34194   clockNow$1 = 0;
34195 }
34196
34197 function Timer$1() {
34198   this._call =
34199   this._time =
34200   this._next = null;
34201 }
34202
34203 Timer$1.prototype = timer$1.prototype = {
34204   constructor: Timer$1,
34205   restart: function(callback, delay, time) {
34206     if (typeof callback !== "function") throw new TypeError("callback is not a function");
34207     time = (time == null ? now$1() : +time) + (delay == null ? 0 : +delay);
34208     if (!this._next && taskTail$1 !== this) {
34209       if (taskTail$1) taskTail$1._next = this;
34210       else taskHead$1 = this;
34211       taskTail$1 = this;
34212     }
34213     this._call = callback;
34214     this._time = time;
34215     sleep$1();
34216   },
34217   stop: function() {
34218     if (this._call) {
34219       this._call = null;
34220       this._time = Infinity;
34221       sleep$1();
34222     }
34223   }
34224 };
34225
34226 function timer$1(callback, delay, time) {
34227   var t = new Timer$1;
34228   t.restart(callback, delay, time);
34229   return t;
34230 }
34231
34232 function timerFlush$1() {
34233   now$1(); // Get the current time, if not already set.
34234   ++frame$1; // Pretend we’ve set an alarm, if we haven’t already.
34235   var t = taskHead$1, e;
34236   while (t) {
34237     if ((e = clockNow$1 - t._time) >= 0) t._call.call(null, e);
34238     t = t._next;
34239   }
34240   --frame$1;
34241 }
34242
34243 function wake$1() {
34244   clockNow$1 = (clockLast$1 = clock$1.now()) + clockSkew$1;
34245   frame$1 = timeout$2 = 0;
34246   try {
34247     timerFlush$1();
34248   } finally {
34249     frame$1 = 0;
34250     nap$1();
34251     clockNow$1 = 0;
34252   }
34253 }
34254
34255 function poke$2() {
34256   var now = clock$1.now(), delay = now - clockLast$1;
34257   if (delay > pokeDelay$1) clockSkew$1 -= delay, clockLast$1 = now;
34258 }
34259
34260 function nap$1() {
34261   var t0, t1 = taskHead$1, t2, time = Infinity;
34262   while (t1) {
34263     if (t1._call) {
34264       if (time > t1._time) time = t1._time;
34265       t0 = t1, t1 = t1._next;
34266     } else {
34267       t2 = t1._next, t1._next = null;
34268       t1 = t0 ? t0._next = t2 : taskHead$1 = t2;
34269     }
34270   }
34271   taskTail$1 = t0;
34272   sleep$1(time);
34273 }
34274
34275 function sleep$1(time) {
34276   if (frame$1) return; // Soonest alarm already set, or will be.
34277   if (timeout$2) timeout$2 = clearTimeout(timeout$2);
34278   var delay = time - clockNow$1;
34279   if (delay > 24) {
34280     if (time < Infinity) timeout$2 = setTimeout(wake$1, delay);
34281     if (interval$2) interval$2 = clearInterval(interval$2);
34282   } else {
34283     if (!interval$2) clockLast$1 = clockNow$1, interval$2 = setInterval(poke$2, pokeDelay$1);
34284     frame$1 = 1, setFrame$1(wake$1);
34285   }
34286 }
34287
34288 var timeout$3 = function(callback, delay, time) {
34289   var t = new Timer$1;
34290   delay = delay == null ? 0 : +delay;
34291   t.restart(function(elapsed) {
34292     t.stop();
34293     callback(elapsed + delay);
34294   }, delay, time);
34295   return t;
34296 };
34297
34298 var interval$3 = function(callback, delay, time) {
34299   var t = new Timer$1, total = delay;
34300   if (delay == null) return t.restart(callback, delay, time), t;
34301   delay = +delay, time = time == null ? now$1() : +time;
34302   t.restart(function tick(elapsed) {
34303     elapsed += total;
34304     t.restart(tick, total += delay, time);
34305     callback(elapsed);
34306   }, delay, time);
34307   return t;
34308 };
34309
34310 var constant$12 = function(x) {
34311   return function() {
34312     return x;
34313   };
34314 };
34315
34316 function x$4(d) {
34317   return d[0];
34318 }
34319
34320 function y$4(d) {
34321   return d[1];
34322 }
34323
34324 function RedBlackTree() {
34325   this._ = null; // root node
34326 }
34327
34328 function RedBlackNode(node) {
34329   node.U = // parent node
34330   node.C = // color - true for red, false for black
34331   node.L = // left node
34332   node.R = // right node
34333   node.P = // previous node
34334   node.N = null; // next node
34335 }
34336
34337 RedBlackTree.prototype = {
34338   constructor: RedBlackTree,
34339
34340   insert: function(after, node) {
34341     var parent, grandpa, uncle;
34342
34343     if (after) {
34344       node.P = after;
34345       node.N = after.N;
34346       if (after.N) after.N.P = node;
34347       after.N = node;
34348       if (after.R) {
34349         after = after.R;
34350         while (after.L) after = after.L;
34351         after.L = node;
34352       } else {
34353         after.R = node;
34354       }
34355       parent = after;
34356     } else if (this._) {
34357       after = RedBlackFirst(this._);
34358       node.P = null;
34359       node.N = after;
34360       after.P = after.L = node;
34361       parent = after;
34362     } else {
34363       node.P = node.N = null;
34364       this._ = node;
34365       parent = null;
34366     }
34367     node.L = node.R = null;
34368     node.U = parent;
34369     node.C = true;
34370
34371     after = node;
34372     while (parent && parent.C) {
34373       grandpa = parent.U;
34374       if (parent === grandpa.L) {
34375         uncle = grandpa.R;
34376         if (uncle && uncle.C) {
34377           parent.C = uncle.C = false;
34378           grandpa.C = true;
34379           after = grandpa;
34380         } else {
34381           if (after === parent.R) {
34382             RedBlackRotateLeft(this, parent);
34383             after = parent;
34384             parent = after.U;
34385           }
34386           parent.C = false;
34387           grandpa.C = true;
34388           RedBlackRotateRight(this, grandpa);
34389         }
34390       } else {
34391         uncle = grandpa.L;
34392         if (uncle && uncle.C) {
34393           parent.C = uncle.C = false;
34394           grandpa.C = true;
34395           after = grandpa;
34396         } else {
34397           if (after === parent.L) {
34398             RedBlackRotateRight(this, parent);
34399             after = parent;
34400             parent = after.U;
34401           }
34402           parent.C = false;
34403           grandpa.C = true;
34404           RedBlackRotateLeft(this, grandpa);
34405         }
34406       }
34407       parent = after.U;
34408     }
34409     this._.C = false;
34410   },
34411
34412   remove: function(node) {
34413     if (node.N) node.N.P = node.P;
34414     if (node.P) node.P.N = node.N;
34415     node.N = node.P = null;
34416
34417     var parent = node.U,
34418         sibling,
34419         left = node.L,
34420         right = node.R,
34421         next,
34422         red;
34423
34424     if (!left) next = right;
34425     else if (!right) next = left;
34426     else next = RedBlackFirst(right);
34427
34428     if (parent) {
34429       if (parent.L === node) parent.L = next;
34430       else parent.R = next;
34431     } else {
34432       this._ = next;
34433     }
34434
34435     if (left && right) {
34436       red = next.C;
34437       next.C = node.C;
34438       next.L = left;
34439       left.U = next;
34440       if (next !== right) {
34441         parent = next.U;
34442         next.U = node.U;
34443         node = next.R;
34444         parent.L = node;
34445         next.R = right;
34446         right.U = next;
34447       } else {
34448         next.U = parent;
34449         parent = next;
34450         node = next.R;
34451       }
34452     } else {
34453       red = node.C;
34454       node = next;
34455     }
34456
34457     if (node) node.U = parent;
34458     if (red) return;
34459     if (node && node.C) { node.C = false; return; }
34460
34461     do {
34462       if (node === this._) break;
34463       if (node === parent.L) {
34464         sibling = parent.R;
34465         if (sibling.C) {
34466           sibling.C = false;
34467           parent.C = true;
34468           RedBlackRotateLeft(this, parent);
34469           sibling = parent.R;
34470         }
34471         if ((sibling.L && sibling.L.C)
34472             || (sibling.R && sibling.R.C)) {
34473           if (!sibling.R || !sibling.R.C) {
34474             sibling.L.C = false;
34475             sibling.C = true;
34476             RedBlackRotateRight(this, sibling);
34477             sibling = parent.R;
34478           }
34479           sibling.C = parent.C;
34480           parent.C = sibling.R.C = false;
34481           RedBlackRotateLeft(this, parent);
34482           node = this._;
34483           break;
34484         }
34485       } else {
34486         sibling = parent.L;
34487         if (sibling.C) {
34488           sibling.C = false;
34489           parent.C = true;
34490           RedBlackRotateRight(this, parent);
34491           sibling = parent.L;
34492         }
34493         if ((sibling.L && sibling.L.C)
34494           || (sibling.R && sibling.R.C)) {
34495           if (!sibling.L || !sibling.L.C) {
34496             sibling.R.C = false;
34497             sibling.C = true;
34498             RedBlackRotateLeft(this, sibling);
34499             sibling = parent.L;
34500           }
34501           sibling.C = parent.C;
34502           parent.C = sibling.L.C = false;
34503           RedBlackRotateRight(this, parent);
34504           node = this._;
34505           break;
34506         }
34507       }
34508       sibling.C = true;
34509       node = parent;
34510       parent = parent.U;
34511     } while (!node.C);
34512
34513     if (node) node.C = false;
34514   }
34515 };
34516
34517 function RedBlackRotateLeft(tree, node) {
34518   var p = node,
34519       q = node.R,
34520       parent = p.U;
34521
34522   if (parent) {
34523     if (parent.L === p) parent.L = q;
34524     else parent.R = q;
34525   } else {
34526     tree._ = q;
34527   }
34528
34529   q.U = parent;
34530   p.U = q;
34531   p.R = q.L;
34532   if (p.R) p.R.U = p;
34533   q.L = p;
34534 }
34535
34536 function RedBlackRotateRight(tree, node) {
34537   var p = node,
34538       q = node.L,
34539       parent = p.U;
34540
34541   if (parent) {
34542     if (parent.L === p) parent.L = q;
34543     else parent.R = q;
34544   } else {
34545     tree._ = q;
34546   }
34547
34548   q.U = parent;
34549   p.U = q;
34550   p.L = q.R;
34551   if (p.L) p.L.U = p;
34552   q.R = p;
34553 }
34554
34555 function RedBlackFirst(node) {
34556   while (node.L) node = node.L;
34557   return node;
34558 }
34559
34560 function createEdge(left, right, v0, v1) {
34561   var edge = [null, null],
34562       index = edges.push(edge) - 1;
34563   edge.left = left;
34564   edge.right = right;
34565   if (v0) setEdgeEnd(edge, left, right, v0);
34566   if (v1) setEdgeEnd(edge, right, left, v1);
34567   cells[left.index].halfedges.push(index);
34568   cells[right.index].halfedges.push(index);
34569   return edge;
34570 }
34571
34572 function createBorderEdge(left, v0, v1) {
34573   var edge = [v0, v1];
34574   edge.left = left;
34575   return edge;
34576 }
34577
34578 function setEdgeEnd(edge, left, right, vertex) {
34579   if (!edge[0] && !edge[1]) {
34580     edge[0] = vertex;
34581     edge.left = left;
34582     edge.right = right;
34583   } else if (edge.left === right) {
34584     edge[1] = vertex;
34585   } else {
34586     edge[0] = vertex;
34587   }
34588 }
34589
34590 // Liang–Barsky line clipping.
34591 function clipEdge(edge, x0, y0, x1, y1) {
34592   var a = edge[0],
34593       b = edge[1],
34594       ax = a[0],
34595       ay = a[1],
34596       bx = b[0],
34597       by = b[1],
34598       t0 = 0,
34599       t1 = 1,
34600       dx = bx - ax,
34601       dy = by - ay,
34602       r;
34603
34604   r = x0 - ax;
34605   if (!dx && r > 0) return;
34606   r /= dx;
34607   if (dx < 0) {
34608     if (r < t0) return;
34609     if (r < t1) t1 = r;
34610   } else if (dx > 0) {
34611     if (r > t1) return;
34612     if (r > t0) t0 = r;
34613   }
34614
34615   r = x1 - ax;
34616   if (!dx && r < 0) return;
34617   r /= dx;
34618   if (dx < 0) {
34619     if (r > t1) return;
34620     if (r > t0) t0 = r;
34621   } else if (dx > 0) {
34622     if (r < t0) return;
34623     if (r < t1) t1 = r;
34624   }
34625
34626   r = y0 - ay;
34627   if (!dy && r > 0) return;
34628   r /= dy;
34629   if (dy < 0) {
34630     if (r < t0) return;
34631     if (r < t1) t1 = r;
34632   } else if (dy > 0) {
34633     if (r > t1) return;
34634     if (r > t0) t0 = r;
34635   }
34636
34637   r = y1 - ay;
34638   if (!dy && r < 0) return;
34639   r /= dy;
34640   if (dy < 0) {
34641     if (r > t1) return;
34642     if (r > t0) t0 = r;
34643   } else if (dy > 0) {
34644     if (r < t0) return;
34645     if (r < t1) t1 = r;
34646   }
34647
34648   if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
34649
34650   if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
34651   if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
34652   return true;
34653 }
34654
34655 function connectEdge(edge, x0, y0, x1, y1) {
34656   var v1 = edge[1];
34657   if (v1) return true;
34658
34659   var v0 = edge[0],
34660       left = edge.left,
34661       right = edge.right,
34662       lx = left[0],
34663       ly = left[1],
34664       rx = right[0],
34665       ry = right[1],
34666       fx = (lx + rx) / 2,
34667       fy = (ly + ry) / 2,
34668       fm,
34669       fb;
34670
34671   if (ry === ly) {
34672     if (fx < x0 || fx >= x1) return;
34673     if (lx > rx) {
34674       if (!v0) v0 = [fx, y0];
34675       else if (v0[1] >= y1) return;
34676       v1 = [fx, y1];
34677     } else {
34678       if (!v0) v0 = [fx, y1];
34679       else if (v0[1] < y0) return;
34680       v1 = [fx, y0];
34681     }
34682   } else {
34683     fm = (lx - rx) / (ry - ly);
34684     fb = fy - fm * fx;
34685     if (fm < -1 || fm > 1) {
34686       if (lx > rx) {
34687         if (!v0) v0 = [(y0 - fb) / fm, y0];
34688         else if (v0[1] >= y1) return;
34689         v1 = [(y1 - fb) / fm, y1];
34690       } else {
34691         if (!v0) v0 = [(y1 - fb) / fm, y1];
34692         else if (v0[1] < y0) return;
34693         v1 = [(y0 - fb) / fm, y0];
34694       }
34695     } else {
34696       if (ly < ry) {
34697         if (!v0) v0 = [x0, fm * x0 + fb];
34698         else if (v0[0] >= x1) return;
34699         v1 = [x1, fm * x1 + fb];
34700       } else {
34701         if (!v0) v0 = [x1, fm * x1 + fb];
34702         else if (v0[0] < x0) return;
34703         v1 = [x0, fm * x0 + fb];
34704       }
34705     }
34706   }
34707
34708   edge[0] = v0;
34709   edge[1] = v1;
34710   return true;
34711 }
34712
34713 function clipEdges(x0, y0, x1, y1) {
34714   var i = edges.length,
34715       edge;
34716
34717   while (i--) {
34718     if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
34719         || !clipEdge(edge, x0, y0, x1, y1)
34720         || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4
34721             || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) {
34722       delete edges[i];
34723     }
34724   }
34725 }
34726
34727 function createCell(site) {
34728   return cells[site.index] = {
34729     site: site,
34730     halfedges: []
34731   };
34732 }
34733
34734 function cellHalfedgeAngle(cell, edge) {
34735   var site = cell.site,
34736       va = edge.left,
34737       vb = edge.right;
34738   if (site === vb) vb = va, va = site;
34739   if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
34740   if (site === va) va = edge[1], vb = edge[0];
34741   else va = edge[0], vb = edge[1];
34742   return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
34743 }
34744
34745 function cellHalfedgeStart(cell, edge) {
34746   return edge[+(edge.left !== cell.site)];
34747 }
34748
34749 function cellHalfedgeEnd(cell, edge) {
34750   return edge[+(edge.left === cell.site)];
34751 }
34752
34753 function sortCellHalfedges() {
34754   for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
34755     if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
34756       var index = new Array(m),
34757           array = new Array(m);
34758       for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
34759       index.sort(function(i, j) { return array[j] - array[i]; });
34760       for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
34761       for (j = 0; j < m; ++j) halfedges[j] = array[j];
34762     }
34763   }
34764 }
34765
34766 function clipCells(x0, y0, x1, y1) {
34767   var nCells = cells.length,
34768       iCell,
34769       cell,
34770       site,
34771       iHalfedge,
34772       halfedges,
34773       nHalfedges,
34774       start,
34775       startX,
34776       startY,
34777       end,
34778       endX,
34779       endY,
34780       cover = true;
34781
34782   for (iCell = 0; iCell < nCells; ++iCell) {
34783     if (cell = cells[iCell]) {
34784       site = cell.site;
34785       halfedges = cell.halfedges;
34786       iHalfedge = halfedges.length;
34787
34788       // Remove any dangling clipped edges.
34789       while (iHalfedge--) {
34790         if (!edges[halfedges[iHalfedge]]) {
34791           halfedges.splice(iHalfedge, 1);
34792         }
34793       }
34794
34795       // Insert any border edges as necessary.
34796       iHalfedge = 0, nHalfedges = halfedges.length;
34797       while (iHalfedge < nHalfedges) {
34798         end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
34799         start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
34800         if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) {
34801           halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
34802               Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1]
34803               : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1]
34804               : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0]
34805               : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0]
34806               : null)) - 1);
34807           ++nHalfedges;
34808         }
34809       }
34810
34811       if (nHalfedges) cover = false;
34812     }
34813   }
34814
34815   // If there weren’t any edges, have the closest site cover the extent.
34816   // It doesn’t matter which corner of the extent we measure!
34817   if (cover) {
34818     var dx, dy, d2, dc = Infinity;
34819
34820     for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
34821       if (cell = cells[iCell]) {
34822         site = cell.site;
34823         dx = site[0] - x0;
34824         dy = site[1] - y0;
34825         d2 = dx * dx + dy * dy;
34826         if (d2 < dc) dc = d2, cover = cell;
34827       }
34828     }
34829
34830     if (cover) {
34831       var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
34832       cover.halfedges.push(
34833         edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
34834         edges.push(createBorderEdge(site, v01, v11)) - 1,
34835         edges.push(createBorderEdge(site, v11, v10)) - 1,
34836         edges.push(createBorderEdge(site, v10, v00)) - 1
34837       );
34838     }
34839   }
34840
34841   // Lastly delete any cells with no edges; these were entirely clipped.
34842   for (iCell = 0; iCell < nCells; ++iCell) {
34843     if (cell = cells[iCell]) {
34844       if (!cell.halfedges.length) {
34845         delete cells[iCell];
34846       }
34847     }
34848   }
34849 }
34850
34851 var circlePool = [];
34852
34853 var firstCircle;
34854
34855 function Circle() {
34856   RedBlackNode(this);
34857   this.x =
34858   this.y =
34859   this.arc =
34860   this.site =
34861   this.cy = null;
34862 }
34863
34864 function attachCircle(arc) {
34865   var lArc = arc.P,
34866       rArc = arc.N;
34867
34868   if (!lArc || !rArc) return;
34869
34870   var lSite = lArc.site,
34871       cSite = arc.site,
34872       rSite = rArc.site;
34873
34874   if (lSite === rSite) return;
34875
34876   var bx = cSite[0],
34877       by = cSite[1],
34878       ax = lSite[0] - bx,
34879       ay = lSite[1] - by,
34880       cx = rSite[0] - bx,
34881       cy = rSite[1] - by;
34882
34883   var d = 2 * (ax * cy - ay * cx);
34884   if (d >= -epsilon2$3) return;
34885
34886   var ha = ax * ax + ay * ay,
34887       hc = cx * cx + cy * cy,
34888       x = (cy * ha - ay * hc) / d,
34889       y = (ax * hc - cx * ha) / d;
34890
34891   var circle = circlePool.pop() || new Circle;
34892   circle.arc = arc;
34893   circle.site = cSite;
34894   circle.x = x + bx;
34895   circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
34896
34897   arc.circle = circle;
34898
34899   var before = null,
34900       node = circles._;
34901
34902   while (node) {
34903     if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
34904       if (node.L) node = node.L;
34905       else { before = node.P; break; }
34906     } else {
34907       if (node.R) node = node.R;
34908       else { before = node; break; }
34909     }
34910   }
34911
34912   circles.insert(before, circle);
34913   if (!before) firstCircle = circle;
34914 }
34915
34916 function detachCircle(arc) {
34917   var circle = arc.circle;
34918   if (circle) {
34919     if (!circle.P) firstCircle = circle.N;
34920     circles.remove(circle);
34921     circlePool.push(circle);
34922     RedBlackNode(circle);
34923     arc.circle = null;
34924   }
34925 }
34926
34927 var beachPool = [];
34928
34929 function Beach() {
34930   RedBlackNode(this);
34931   this.edge =
34932   this.site =
34933   this.circle = null;
34934 }
34935
34936 function createBeach(site) {
34937   var beach = beachPool.pop() || new Beach;
34938   beach.site = site;
34939   return beach;
34940 }
34941
34942 function detachBeach(beach) {
34943   detachCircle(beach);
34944   beaches.remove(beach);
34945   beachPool.push(beach);
34946   RedBlackNode(beach);
34947 }
34948
34949 function removeBeach(beach) {
34950   var circle = beach.circle,
34951       x = circle.x,
34952       y = circle.cy,
34953       vertex = [x, y],
34954       previous = beach.P,
34955       next = beach.N,
34956       disappearing = [beach];
34957
34958   detachBeach(beach);
34959
34960   var lArc = previous;
34961   while (lArc.circle
34962       && Math.abs(x - lArc.circle.x) < epsilon$4
34963       && Math.abs(y - lArc.circle.cy) < epsilon$4) {
34964     previous = lArc.P;
34965     disappearing.unshift(lArc);
34966     detachBeach(lArc);
34967     lArc = previous;
34968   }
34969
34970   disappearing.unshift(lArc);
34971   detachCircle(lArc);
34972
34973   var rArc = next;
34974   while (rArc.circle
34975       && Math.abs(x - rArc.circle.x) < epsilon$4
34976       && Math.abs(y - rArc.circle.cy) < epsilon$4) {
34977     next = rArc.N;
34978     disappearing.push(rArc);
34979     detachBeach(rArc);
34980     rArc = next;
34981   }
34982
34983   disappearing.push(rArc);
34984   detachCircle(rArc);
34985
34986   var nArcs = disappearing.length,
34987       iArc;
34988   for (iArc = 1; iArc < nArcs; ++iArc) {
34989     rArc = disappearing[iArc];
34990     lArc = disappearing[iArc - 1];
34991     setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
34992   }
34993
34994   lArc = disappearing[0];
34995   rArc = disappearing[nArcs - 1];
34996   rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
34997
34998   attachCircle(lArc);
34999   attachCircle(rArc);
35000 }
35001
35002 function addBeach(site) {
35003   var x = site[0],
35004       directrix = site[1],
35005       lArc,
35006       rArc,
35007       dxl,
35008       dxr,
35009       node = beaches._;
35010
35011   while (node) {
35012     dxl = leftBreakPoint(node, directrix) - x;
35013     if (dxl > epsilon$4) node = node.L; else {
35014       dxr = x - rightBreakPoint(node, directrix);
35015       if (dxr > epsilon$4) {
35016         if (!node.R) {
35017           lArc = node;
35018           break;
35019         }
35020         node = node.R;
35021       } else {
35022         if (dxl > -epsilon$4) {
35023           lArc = node.P;
35024           rArc = node;
35025         } else if (dxr > -epsilon$4) {
35026           lArc = node;
35027           rArc = node.N;
35028         } else {
35029           lArc = rArc = node;
35030         }
35031         break;
35032       }
35033     }
35034   }
35035
35036   createCell(site);
35037   var newArc = createBeach(site);
35038   beaches.insert(lArc, newArc);
35039
35040   if (!lArc && !rArc) return;
35041
35042   if (lArc === rArc) {
35043     detachCircle(lArc);
35044     rArc = createBeach(lArc.site);
35045     beaches.insert(newArc, rArc);
35046     newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
35047     attachCircle(lArc);
35048     attachCircle(rArc);
35049     return;
35050   }
35051
35052   if (!rArc) { // && lArc
35053     newArc.edge = createEdge(lArc.site, newArc.site);
35054     return;
35055   }
35056
35057   // else lArc !== rArc
35058   detachCircle(lArc);
35059   detachCircle(rArc);
35060
35061   var lSite = lArc.site,
35062       ax = lSite[0],
35063       ay = lSite[1],
35064       bx = site[0] - ax,
35065       by = site[1] - ay,
35066       rSite = rArc.site,
35067       cx = rSite[0] - ax,
35068       cy = rSite[1] - ay,
35069       d = 2 * (bx * cy - by * cx),
35070       hb = bx * bx + by * by,
35071       hc = cx * cx + cy * cy,
35072       vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
35073
35074   setEdgeEnd(rArc.edge, lSite, rSite, vertex);
35075   newArc.edge = createEdge(lSite, site, null, vertex);
35076   rArc.edge = createEdge(site, rSite, null, vertex);
35077   attachCircle(lArc);
35078   attachCircle(rArc);
35079 }
35080
35081 function leftBreakPoint(arc, directrix) {
35082   var site = arc.site,
35083       rfocx = site[0],
35084       rfocy = site[1],
35085       pby2 = rfocy - directrix;
35086
35087   if (!pby2) return rfocx;
35088
35089   var lArc = arc.P;
35090   if (!lArc) return -Infinity;
35091
35092   site = lArc.site;
35093   var lfocx = site[0],
35094       lfocy = site[1],
35095       plby2 = lfocy - directrix;
35096
35097   if (!plby2) return lfocx;
35098
35099   var hl = lfocx - rfocx,
35100       aby2 = 1 / pby2 - 1 / plby2,
35101       b = hl / plby2;
35102
35103   if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
35104
35105   return (rfocx + lfocx) / 2;
35106 }
35107
35108 function rightBreakPoint(arc, directrix) {
35109   var rArc = arc.N;
35110   if (rArc) return leftBreakPoint(rArc, directrix);
35111   var site = arc.site;
35112   return site[1] === directrix ? site[0] : Infinity;
35113 }
35114
35115 var epsilon$4 = 1e-6;
35116 var epsilon2$3 = 1e-12;
35117 var beaches;
35118 var cells;
35119 var circles;
35120 var edges;
35121
35122 function triangleArea(a, b, c) {
35123   return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
35124 }
35125
35126 function lexicographic(a, b) {
35127   return b[1] - a[1]
35128       || b[0] - a[0];
35129 }
35130
35131 function Diagram(sites, extent) {
35132   var site = sites.sort(lexicographic).pop(),
35133       x,
35134       y,
35135       circle;
35136
35137   edges = [];
35138   cells = new Array(sites.length);
35139   beaches = new RedBlackTree;
35140   circles = new RedBlackTree;
35141
35142   while (true) {
35143     circle = firstCircle;
35144     if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
35145       if (site[0] !== x || site[1] !== y) {
35146         addBeach(site);
35147         x = site[0], y = site[1];
35148       }
35149       site = sites.pop();
35150     } else if (circle) {
35151       removeBeach(circle.arc);
35152     } else {
35153       break;
35154     }
35155   }
35156
35157   sortCellHalfedges();
35158
35159   if (extent) {
35160     var x0 = +extent[0][0],
35161         y0 = +extent[0][1],
35162         x1 = +extent[1][0],
35163         y1 = +extent[1][1];
35164     clipEdges(x0, y0, x1, y1);
35165     clipCells(x0, y0, x1, y1);
35166   }
35167
35168   this.edges = edges;
35169   this.cells = cells;
35170
35171   beaches =
35172   circles =
35173   edges =
35174   cells = null;
35175 }
35176
35177 Diagram.prototype = {
35178   constructor: Diagram,
35179
35180   polygons: function() {
35181     var edges = this.edges;
35182
35183     return this.cells.map(function(cell) {
35184       var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
35185       polygon.data = cell.site.data;
35186       return polygon;
35187     });
35188   },
35189
35190   triangles: function() {
35191     var triangles = [],
35192         edges = this.edges;
35193
35194     this.cells.forEach(function(cell, i) {
35195       if (!(m = (halfedges = cell.halfedges).length)) return;
35196       var site = cell.site,
35197           halfedges,
35198           j = -1,
35199           m,
35200           s0,
35201           e1 = edges[halfedges[m - 1]],
35202           s1 = e1.left === site ? e1.right : e1.left;
35203
35204       while (++j < m) {
35205         s0 = s1;
35206         e1 = edges[halfedges[j]];
35207         s1 = e1.left === site ? e1.right : e1.left;
35208         if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
35209           triangles.push([site.data, s0.data, s1.data]);
35210         }
35211       }
35212     });
35213
35214     return triangles;
35215   },
35216
35217   links: function() {
35218     return this.edges.filter(function(edge) {
35219       return edge.right;
35220     }).map(function(edge) {
35221       return {
35222         source: edge.left.data,
35223         target: edge.right.data
35224       };
35225     });
35226   },
35227
35228   find: function(x, y, radius) {
35229     var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell;
35230
35231     // Use the previously-found cell, or start with an arbitrary one.
35232     while (!(cell = that.cells[i1])) if (++i1 >= n) return null;
35233     var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy;
35234
35235     // Traverse the half-edges to find a closer cell, if any.
35236     do {
35237       cell = that.cells[i0 = i1], i1 = null;
35238       cell.halfedges.forEach(function(e) {
35239         var edge = that.edges[e], v = edge.left;
35240         if ((v === cell.site || !v) && !(v = edge.right)) return;
35241         var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy;
35242         if (v2 < d2) d2 = v2, i1 = v.index;
35243       });
35244     } while (i1 !== null);
35245
35246     that._found = i0;
35247
35248     return radius == null || d2 <= radius * radius ? cell.site : null;
35249   }
35250 };
35251
35252 var voronoi = function() {
35253   var x$$1 = x$4,
35254       y$$1 = y$4,
35255       extent = null;
35256
35257   function voronoi(data) {
35258     return new Diagram(data.map(function(d, i) {
35259       var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4];
35260       s.index = i;
35261       s.data = d;
35262       return s;
35263     }), extent);
35264   }
35265
35266   voronoi.polygons = function(data) {
35267     return voronoi(data).polygons();
35268   };
35269
35270   voronoi.links = function(data) {
35271     return voronoi(data).links();
35272   };
35273
35274   voronoi.triangles = function(data) {
35275     return voronoi(data).triangles();
35276   };
35277
35278   voronoi.x = function(_) {
35279     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$12(+_), voronoi) : x$$1;
35280   };
35281
35282   voronoi.y = function(_) {
35283     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$12(+_), voronoi) : y$$1;
35284   };
35285
35286   voronoi.extent = function(_) {
35287     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]]];
35288   };
35289
35290   voronoi.size = function(_) {
35291     return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
35292   };
35293
35294   return voronoi;
35295 };
35296
35297 var constant$13 = function(x) {
35298   return function() {
35299     return x;
35300   };
35301 };
35302
35303 function ZoomEvent(target, type, transform) {
35304   this.target = target;
35305   this.type = type;
35306   this.transform = transform;
35307 }
35308
35309 function Transform(k, x, y) {
35310   this.k = k;
35311   this.x = x;
35312   this.y = y;
35313 }
35314
35315 Transform.prototype = {
35316   constructor: Transform,
35317   scale: function(k) {
35318     return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
35319   },
35320   translate: function(x, y) {
35321     return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
35322   },
35323   apply: function(point) {
35324     return [point[0] * this.k + this.x, point[1] * this.k + this.y];
35325   },
35326   applyX: function(x) {
35327     return x * this.k + this.x;
35328   },
35329   applyY: function(y) {
35330     return y * this.k + this.y;
35331   },
35332   invert: function(location) {
35333     return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
35334   },
35335   invertX: function(x) {
35336     return (x - this.x) / this.k;
35337   },
35338   invertY: function(y) {
35339     return (y - this.y) / this.k;
35340   },
35341   rescaleX: function(x) {
35342     return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
35343   },
35344   rescaleY: function(y) {
35345     return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
35346   },
35347   toString: function() {
35348     return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
35349   }
35350 };
35351
35352 var identity$9 = new Transform(1, 0, 0);
35353
35354 transform$1.prototype = Transform.prototype;
35355
35356 function transform$1(node) {
35357   return node.__zoom || identity$9;
35358 }
35359
35360 function nopropagation$2() {
35361   event.stopImmediatePropagation();
35362 }
35363
35364 var noevent$2 = function() {
35365   event.preventDefault();
35366   event.stopImmediatePropagation();
35367 };
35368
35369 // Ignore right-click, since that should open the context menu.
35370 function defaultFilter$2() {
35371   return !event.button;
35372 }
35373
35374 function defaultExtent$1() {
35375   var e = this, w, h;
35376   if (e instanceof SVGElement) {
35377     e = e.ownerSVGElement || e;
35378     w = e.width.baseVal.value;
35379     h = e.height.baseVal.value;
35380   } else {
35381     w = e.clientWidth;
35382     h = e.clientHeight;
35383   }
35384   return [[0, 0], [w, h]];
35385 }
35386
35387 function defaultTransform() {
35388   return this.__zoom || identity$9;
35389 }
35390
35391 var zoom$1 = function() {
35392   var filter = defaultFilter$2,
35393       extent = defaultExtent$1,
35394       k0 = 0,
35395       k1 = Infinity,
35396       x0 = -k1,
35397       x1 = k1,
35398       y0 = x0,
35399       y1 = x1,
35400       duration = 250,
35401       interpolate$$1 = interpolateZoom,
35402       gestures = [],
35403       listeners = dispatch("start", "zoom", "end"),
35404       touchstarting,
35405       touchending,
35406       touchDelay = 500,
35407       wheelDelay = 150;
35408
35409   function zoom(selection$$1) {
35410     selection$$1
35411         .on("wheel.zoom", wheeled)
35412         .on("mousedown.zoom", mousedowned)
35413         .on("dblclick.zoom", dblclicked)
35414         .on("touchstart.zoom", touchstarted)
35415         .on("touchmove.zoom", touchmoved)
35416         .on("touchend.zoom touchcancel.zoom", touchended)
35417         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
35418         .property("__zoom", defaultTransform);
35419   }
35420
35421   zoom.transform = function(collection, transform) {
35422     var selection$$1 = collection.selection ? collection.selection() : collection;
35423     selection$$1.property("__zoom", defaultTransform);
35424     if (collection !== selection$$1) {
35425       schedule(collection, transform);
35426     } else {
35427       selection$$1.interrupt().each(function() {
35428         gesture(this, arguments)
35429             .start()
35430             .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
35431             .end();
35432       });
35433     }
35434   };
35435
35436   zoom.scaleBy = function(selection$$1, k) {
35437     zoom.scaleTo(selection$$1, function() {
35438       var k0 = this.__zoom.k,
35439           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35440       return k0 * k1;
35441     });
35442   };
35443
35444   zoom.scaleTo = function(selection$$1, k) {
35445     zoom.transform(selection$$1, function() {
35446       var e = extent.apply(this, arguments),
35447           t0 = this.__zoom,
35448           p0 = centroid(e),
35449           p1 = t0.invert(p0),
35450           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
35451       return constrain(translate(scale(t0, k1), p0, p1), e);
35452     });
35453   };
35454
35455   zoom.translateBy = function(selection$$1, x, y) {
35456     zoom.transform(selection$$1, function() {
35457       return constrain(this.__zoom.translate(
35458         typeof x === "function" ? x.apply(this, arguments) : x,
35459         typeof y === "function" ? y.apply(this, arguments) : y
35460       ), extent.apply(this, arguments));
35461     });
35462   };
35463
35464   function scale(transform, k) {
35465     k = Math.max(k0, Math.min(k1, k));
35466     return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
35467   }
35468
35469   function translate(transform, p0, p1) {
35470     var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
35471     return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
35472   }
35473
35474   function constrain(transform, extent) {
35475     var dx0 = transform.invertX(extent[0][0]) - x0,
35476         dx1 = transform.invertX(extent[1][0]) - x1,
35477         dy0 = transform.invertY(extent[0][1]) - y0,
35478         dy1 = transform.invertY(extent[1][1]) - y1;
35479     return transform.translate(
35480       dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
35481       dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
35482     );
35483   }
35484
35485   function centroid(extent) {
35486     return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
35487   }
35488
35489   function schedule(transition$$1, transform, center) {
35490     transition$$1
35491         .on("start.zoom", function() { gesture(this, arguments).start(); })
35492         .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
35493         .tween("zoom", function() {
35494           var that = this,
35495               args = arguments,
35496               g = gesture(that, args),
35497               e = extent.apply(that, args),
35498               p = center || centroid(e),
35499               w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
35500               a = that.__zoom,
35501               b = typeof transform === "function" ? transform.apply(that, args) : transform,
35502               i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
35503           return function(t) {
35504             if (t === 1) t = b; // Avoid rounding error on end.
35505             else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
35506             g.zoom(null, t);
35507           };
35508         });
35509   }
35510
35511   function gesture(that, args) {
35512     for (var i = 0, n = gestures.length, g; i < n; ++i) {
35513       if ((g = gestures[i]).that === that) {
35514         return g;
35515       }
35516     }
35517     return new Gesture(that, args);
35518   }
35519
35520   function Gesture(that, args) {
35521     this.that = that;
35522     this.args = args;
35523     this.index = -1;
35524     this.active = 0;
35525     this.extent = extent.apply(that, args);
35526   }
35527
35528   Gesture.prototype = {
35529     start: function() {
35530       if (++this.active === 1) {
35531         this.index = gestures.push(this) - 1;
35532         this.emit("start");
35533       }
35534       return this;
35535     },
35536     zoom: function(key, transform) {
35537       if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
35538       if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
35539       if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
35540       this.that.__zoom = transform;
35541       this.emit("zoom");
35542       return this;
35543     },
35544     end: function() {
35545       if (--this.active === 0) {
35546         gestures.splice(this.index, 1);
35547         this.index = -1;
35548         this.emit("end");
35549       }
35550       return this;
35551     },
35552     emit: function(type) {
35553       customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
35554     }
35555   };
35556
35557   function wheeled() {
35558     if (!filter.apply(this, arguments)) return;
35559     var g = gesture(this, arguments),
35560         t = this.__zoom,
35561         k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
35562         p = mouse(this);
35563
35564     // If the mouse is in the same location as before, reuse it.
35565     // If there were recent wheel events, reset the wheel idle timeout.
35566     if (g.wheel) {
35567       if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
35568         g.mouse[1] = t.invert(g.mouse[0] = p);
35569       }
35570       clearTimeout(g.wheel);
35571     }
35572
35573     // If this wheel event won’t trigger a transform change, ignore it.
35574     else if (t.k === k) return;
35575
35576     // Otherwise, capture the mouse point and location at the start.
35577     else {
35578       g.mouse = [p, t.invert(p)];
35579       interrupt(this);
35580       g.start();
35581     }
35582
35583     noevent$2();
35584     g.wheel = setTimeout(wheelidled, wheelDelay);
35585     g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
35586
35587     function wheelidled() {
35588       g.wheel = null;
35589       g.end();
35590     }
35591   }
35592
35593   function mousedowned() {
35594     if (touchending || !filter.apply(this, arguments)) return;
35595     var g = gesture(this, arguments),
35596         v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
35597         p = mouse(this);
35598
35599     dragDisable(event.view);
35600     nopropagation$2();
35601     g.mouse = [p, this.__zoom.invert(p)];
35602     interrupt(this);
35603     g.start();
35604
35605     function mousemoved() {
35606       noevent$2();
35607       g.moved = true;
35608       g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
35609     }
35610
35611     function mouseupped() {
35612       v.on("mousemove.zoom mouseup.zoom", null);
35613       yesdrag(event.view, g.moved);
35614       noevent$2();
35615       g.end();
35616     }
35617   }
35618
35619   function dblclicked() {
35620     if (!filter.apply(this, arguments)) return;
35621     var t0 = this.__zoom,
35622         p0 = mouse(this),
35623         p1 = t0.invert(p0),
35624         k1 = t0.k * (event.shiftKey ? 0.5 : 2),
35625         t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
35626
35627     noevent$2();
35628     if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
35629     else select(this).call(zoom.transform, t1);
35630   }
35631
35632   function touchstarted() {
35633     if (!filter.apply(this, arguments)) return;
35634     var g = gesture(this, arguments),
35635         touches$$1 = event.changedTouches,
35636         started,
35637         n = touches$$1.length, i, t, p;
35638
35639     nopropagation$2();
35640     for (i = 0; i < n; ++i) {
35641       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35642       p = [p, this.__zoom.invert(p), t.identifier];
35643       if (!g.touch0) g.touch0 = p, started = true;
35644       else if (!g.touch1) g.touch1 = p;
35645     }
35646
35647     // If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
35648     if (touchstarting) {
35649       touchstarting = clearTimeout(touchstarting);
35650       if (!g.touch1) {
35651         g.end();
35652         p = select(this).on("dblclick.zoom");
35653         if (p) p.apply(this, arguments);
35654         return;
35655       }
35656     }
35657
35658     if (started) {
35659       touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
35660       interrupt(this);
35661       g.start();
35662     }
35663   }
35664
35665   function touchmoved() {
35666     var g = gesture(this, arguments),
35667         touches$$1 = event.changedTouches,
35668         n = touches$$1.length, i, t, p, l;
35669
35670     noevent$2();
35671     if (touchstarting) touchstarting = clearTimeout(touchstarting);
35672     for (i = 0; i < n; ++i) {
35673       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
35674       if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
35675       else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
35676     }
35677     t = g.that.__zoom;
35678     if (g.touch1) {
35679       var p0 = g.touch0[0], l0 = g.touch0[1],
35680           p1 = g.touch1[0], l1 = g.touch1[1],
35681           dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
35682           dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
35683       t = scale(t, Math.sqrt(dp / dl));
35684       p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
35685       l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
35686     }
35687     else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
35688     else return;
35689     g.zoom("touch", constrain(translate(t, p, l), g.extent));
35690   }
35691
35692   function touchended() {
35693     var g = gesture(this, arguments),
35694         touches$$1 = event.changedTouches,
35695         n = touches$$1.length, i, t;
35696
35697     nopropagation$2();
35698     if (touchending) clearTimeout(touchending);
35699     touchending = setTimeout(function() { touchending = null; }, touchDelay);
35700     for (i = 0; i < n; ++i) {
35701       t = touches$$1[i];
35702       if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
35703       else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
35704     }
35705     if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
35706     if (!g.touch0) g.end();
35707   }
35708
35709   zoom.filter = function(_) {
35710     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$13(!!_), zoom) : filter;
35711   };
35712
35713   zoom.extent = function(_) {
35714     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$13([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
35715   };
35716
35717   zoom.scaleExtent = function(_) {
35718     return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
35719   };
35720
35721   zoom.translateExtent = function(_) {
35722     return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
35723   };
35724
35725   zoom.duration = function(_) {
35726     return arguments.length ? (duration = +_, zoom) : duration;
35727   };
35728
35729   zoom.interpolate = function(_) {
35730     return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1;
35731   };
35732
35733   zoom.on = function() {
35734     var value = listeners.on.apply(listeners, arguments);
35735     return value === listeners ? zoom : value;
35736   };
35737
35738   return zoom;
35739 };
35740
35741
35742
35743 var index$2 = Object.freeze({
35744         version: version,
35745         bisect: bisectRight,
35746         bisectRight: bisectRight,
35747         bisectLeft: bisectLeft,
35748         ascending: ascending,
35749         bisector: bisector,
35750         descending: descending,
35751         deviation: deviation,
35752         extent: extent,
35753         histogram: histogram,
35754         thresholdFreedmanDiaconis: freedmanDiaconis,
35755         thresholdScott: scott,
35756         thresholdSturges: sturges,
35757         max: max,
35758         mean: mean,
35759         median: median,
35760         merge: merge,
35761         min: min,
35762         pairs: pairs,
35763         permute: permute,
35764         quantile: threshold,
35765         range: sequence,
35766         scan: scan,
35767         shuffle: shuffle,
35768         sum: sum,
35769         ticks: ticks,
35770         tickStep: tickStep,
35771         transpose: transpose,
35772         variance: variance,
35773         zip: zip,
35774         axisTop: axisTop,
35775         axisRight: axisRight,
35776         axisBottom: axisBottom,
35777         axisLeft: axisLeft,
35778         brush: brush,
35779         brushX: brushX,
35780         brushY: brushY,
35781         brushSelection: brushSelection,
35782         chord: chord,
35783         ribbon: ribbon,
35784         nest: nest,
35785         set: set$2,
35786         map: map$1,
35787         keys: keys,
35788         values: values,
35789         entries: entries,
35790         color: color,
35791         rgb: rgb,
35792         hsl: hsl,
35793         lab: lab,
35794         hcl: hcl,
35795         cubehelix: cubehelix,
35796         dispatch: dispatch,
35797         drag: drag,
35798         dragDisable: dragDisable,
35799         dragEnable: yesdrag,
35800         dsvFormat: dsv,
35801         csvParse: csvParse,
35802         csvParseRows: csvParseRows,
35803         csvFormat: csvFormat,
35804         csvFormatRows: csvFormatRows,
35805         tsvParse: tsvParse,
35806         tsvParseRows: tsvParseRows,
35807         tsvFormat: tsvFormat,
35808         tsvFormatRows: tsvFormatRows,
35809         easeLinear: linear$1,
35810         easeQuad: quadInOut,
35811         easeQuadIn: quadIn,
35812         easeQuadOut: quadOut,
35813         easeQuadInOut: quadInOut,
35814         easeCubic: cubicInOut,
35815         easeCubicIn: cubicIn,
35816         easeCubicOut: cubicOut,
35817         easeCubicInOut: cubicInOut,
35818         easePoly: polyInOut,
35819         easePolyIn: polyIn,
35820         easePolyOut: polyOut,
35821         easePolyInOut: polyInOut,
35822         easeSin: sinInOut,
35823         easeSinIn: sinIn,
35824         easeSinOut: sinOut,
35825         easeSinInOut: sinInOut,
35826         easeExp: expInOut,
35827         easeExpIn: expIn,
35828         easeExpOut: expOut,
35829         easeExpInOut: expInOut,
35830         easeCircle: circleInOut,
35831         easeCircleIn: circleIn,
35832         easeCircleOut: circleOut,
35833         easeCircleInOut: circleInOut,
35834         easeBounce: bounceOut,
35835         easeBounceIn: bounceIn,
35836         easeBounceOut: bounceOut,
35837         easeBounceInOut: bounceInOut,
35838         easeBack: backInOut,
35839         easeBackIn: backIn,
35840         easeBackOut: backOut,
35841         easeBackInOut: backInOut,
35842         easeElastic: elasticOut,
35843         easeElasticIn: elasticIn,
35844         easeElasticOut: elasticOut,
35845         easeElasticInOut: elasticInOut,
35846         forceCenter: center$1,
35847         forceCollide: collide,
35848         forceLink: link,
35849         forceManyBody: manyBody,
35850         forceSimulation: simulation,
35851         forceX: x$2,
35852         forceY: y$2,
35853         formatDefaultLocale: defaultLocale,
35854         get format () { return format; },
35855         get formatPrefix () { return formatPrefix; },
35856         formatLocale: formatLocale,
35857         formatSpecifier: formatSpecifier,
35858         precisionFixed: precisionFixed,
35859         precisionPrefix: precisionPrefix,
35860         precisionRound: precisionRound,
35861         geoArea: area,
35862         geoBounds: bounds,
35863         geoCentroid: d3GeoCentroid,
35864         geoCircle: circle,
35865         geoClipExtent: extent$1,
35866         geoDistance: distance,
35867         geoGraticule: graticule,
35868         geoGraticule10: graticule10,
35869         geoInterpolate: interpolate$1,
35870         geoLength: d3GeoLength,
35871         geoPath: index$4,
35872         geoAlbers: albers,
35873         geoAlbersUsa: albersUsa,
35874         geoAzimuthalEqualArea: azimuthalEqualArea,
35875         geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35876         geoAzimuthalEquidistant: azimuthalEquidistant,
35877         geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35878         geoConicConformal: conicConformal,
35879         geoConicConformalRaw: conicConformalRaw,
35880         geoConicEqualArea: conicEqualArea,
35881         geoConicEqualAreaRaw: conicEqualAreaRaw,
35882         geoConicEquidistant: conicEquidistant,
35883         geoConicEquidistantRaw: conicEquidistantRaw,
35884         geoEquirectangular: equirectangular,
35885         geoEquirectangularRaw: equirectangularRaw,
35886         geoGnomonic: gnomonic,
35887         geoGnomonicRaw: gnomonicRaw,
35888         geoIdentity: identity$5,
35889         geoProjection: projection,
35890         geoProjectionMutator: projectionMutator,
35891         geoMercator: mercator,
35892         geoMercatorRaw: mercatorRaw,
35893         geoOrthographic: orthographic,
35894         geoOrthographicRaw: orthographicRaw,
35895         geoStereographic: stereographic,
35896         geoStereographicRaw: stereographicRaw,
35897         geoTransverseMercator: transverseMercator,
35898         geoTransverseMercatorRaw: transverseMercatorRaw,
35899         geoRotation: rotation,
35900         geoStream: geoStream,
35901         geoTransform: transform,
35902         cluster: cluster,
35903         hierarchy: hierarchy,
35904         pack: index$5,
35905         packSiblings: siblings,
35906         packEnclose: enclose,
35907         partition: partition,
35908         stratify: stratify,
35909         tree: tree,
35910         treemap: index$6,
35911         treemapBinary: binary,
35912         treemapDice: treemapDice,
35913         treemapSlice: treemapSlice,
35914         treemapSliceDice: sliceDice,
35915         treemapSquarify: squarify,
35916         treemapResquarify: resquarify,
35917         interpolate: value$1,
35918         interpolateArray: array$2,
35919         interpolateBasis: basis$3,
35920         interpolateBasisClosed: basisClosed$1,
35921         interpolateDate: date$1,
35922         interpolateNumber: number$1,
35923         interpolateObject: object$2,
35924         interpolateRound: round,
35925         interpolateString: string,
35926         interpolateTransformCss: interpolateTransformCss$1,
35927         interpolateTransformSvg: interpolateTransformSvg$1,
35928         interpolateZoom: interpolateZoom,
35929         interpolateRgb: rgb$1,
35930         interpolateRgbBasis: rgbBasis$1,
35931         interpolateRgbBasisClosed: rgbBasisClosed$1,
35932         interpolateHsl: hsl$4,
35933         interpolateHslLong: hslLong$1,
35934         interpolateLab: lab$2,
35935         interpolateHcl: hcl$4,
35936         interpolateHclLong: hclLong$1,
35937         interpolateCubehelix: cubehelix$4,
35938         interpolateCubehelixLong: cubehelixLong$1,
35939         quantize: quantize$1,
35940         path: path,
35941         polygonArea: d3polygonArea,
35942         polygonCentroid: d3polygonCentroid,
35943         polygonHull: d3polygonHull,
35944         polygonContains: contains,
35945         polygonLength: length$1,
35946         quadtree: quadtree,
35947         queue: queue,
35948         randomUniform: uniform,
35949         randomNormal: normal,
35950         randomLogNormal: logNormal,
35951         randomBates: bates,
35952         randomIrwinHall: irwinHall,
35953         randomExponential: exponential$2,
35954         request: request,
35955         html: html,
35956         json: json,
35957         text: text,
35958         xml: xml,
35959         csv: csv$1,
35960         tsv: tsv$1,
35961         scaleBand: band,
35962         scalePoint: point$1,
35963         scaleIdentity: identity$7,
35964         scaleLinear: linear$3,
35965         scaleLog: log$1,
35966         scaleOrdinal: ordinal,
35967         scaleImplicit: implicit,
35968         scalePow: pow$1,
35969         scaleSqrt: sqrt$1,
35970         scaleQuantile: quantile$$1,
35971         scaleQuantize: quantize$2,
35972         scaleThreshold: threshold$1,
35973         scaleTime: time,
35974         scaleUtc: utcTime,
35975         schemeCategory10: category10,
35976         schemeCategory20b: category20b,
35977         schemeCategory20c: category20c,
35978         schemeCategory20: category20,
35979         interpolateCubehelixDefault: cubehelix$5,
35980         interpolateRainbow: rainbow$1,
35981         interpolateWarm: warm,
35982         interpolateCool: cool,
35983         interpolateViridis: viridis,
35984         interpolateMagma: magma,
35985         interpolateInferno: inferno,
35986         interpolatePlasma: plasma,
35987         scaleSequential: sequential,
35988         creator: creator,
35989         local: local$1,
35990         matcher: matcher$1,
35991         mouse: mouse,
35992         namespace: namespace,
35993         namespaces: namespaces,
35994         select: select,
35995         selectAll: selectAll,
35996         selection: selection,
35997         selector: selector,
35998         selectorAll: selectorAll,
35999         touch: touch,
36000         touches: touches,
36001         window: window$1,
36002         get event () { return event; },
36003         customEvent: customEvent,
36004         arc: arc,
36005         area: area$1,
36006         line: line,
36007         pie: pie,
36008         radialArea: radialArea,
36009         radialLine: radialLine$1,
36010         symbol: symbol,
36011         symbols: symbols,
36012         symbolCircle: circle$2,
36013         symbolCross: cross$1,
36014         symbolDiamond: diamond,
36015         symbolSquare: square,
36016         symbolStar: star,
36017         symbolTriangle: triangle,
36018         symbolWye: wye,
36019         curveBasisClosed: basisClosed$2,
36020         curveBasisOpen: basisOpen,
36021         curveBasis: basis$4,
36022         curveBundle: bundle,
36023         curveCardinalClosed: cardinalClosed,
36024         curveCardinalOpen: cardinalOpen,
36025         curveCardinal: cardinal,
36026         curveCatmullRomClosed: catmullRomClosed,
36027         curveCatmullRomOpen: catmullRomOpen,
36028         curveCatmullRom: catmullRom,
36029         curveLinearClosed: linearClosed,
36030         curveLinear: curveLinear,
36031         curveMonotoneX: monotoneX,
36032         curveMonotoneY: monotoneY,
36033         curveNatural: natural,
36034         curveStep: step,
36035         curveStepAfter: stepAfter,
36036         curveStepBefore: stepBefore,
36037         stack: stack,
36038         stackOffsetExpand: expand,
36039         stackOffsetNone: none$1,
36040         stackOffsetSilhouette: silhouette,
36041         stackOffsetWiggle: wiggle,
36042         stackOrderAscending: ascending$2,
36043         stackOrderDescending: descending$2,
36044         stackOrderInsideOut: insideOut,
36045         stackOrderNone: none$2,
36046         stackOrderReverse: reverse,
36047         timeInterval: newInterval,
36048         timeMillisecond: millisecond,
36049         timeMilliseconds: milliseconds,
36050         utcMillisecond: millisecond,
36051         utcMilliseconds: milliseconds,
36052         timeSecond: second,
36053         timeSeconds: seconds,
36054         utcSecond: second,
36055         utcSeconds: seconds,
36056         timeMinute: minute,
36057         timeMinutes: minutes,
36058         timeHour: hour,
36059         timeHours: hours,
36060         timeDay: day,
36061         timeDays: days,
36062         timeWeek: sunday,
36063         timeWeeks: sundays,
36064         timeSunday: sunday,
36065         timeSundays: sundays,
36066         timeMonday: monday,
36067         timeMondays: mondays,
36068         timeTuesday: tuesday,
36069         timeTuesdays: tuesdays,
36070         timeWednesday: wednesday,
36071         timeWednesdays: wednesdays,
36072         timeThursday: thursday,
36073         timeThursdays: thursdays,
36074         timeFriday: friday,
36075         timeFridays: fridays,
36076         timeSaturday: saturday,
36077         timeSaturdays: saturdays,
36078         timeMonth: month,
36079         timeMonths: months,
36080         timeYear: year,
36081         timeYears: years,
36082         utcMinute: utcMinute,
36083         utcMinutes: utcMinutes,
36084         utcHour: utcHour,
36085         utcHours: utcHours,
36086         utcDay: utcDay,
36087         utcDays: utcDays,
36088         utcWeek: utcSunday,
36089         utcWeeks: utcSundays,
36090         utcSunday: utcSunday,
36091         utcSundays: utcSundays,
36092         utcMonday: utcMonday,
36093         utcMondays: utcMondays,
36094         utcTuesday: utcTuesday,
36095         utcTuesdays: utcTuesdays,
36096         utcWednesday: utcWednesday,
36097         utcWednesdays: utcWednesdays,
36098         utcThursday: utcThursday,
36099         utcThursdays: utcThursdays,
36100         utcFriday: utcFriday,
36101         utcFridays: utcFridays,
36102         utcSaturday: utcSaturday,
36103         utcSaturdays: utcSaturdays,
36104         utcMonth: utcMonth,
36105         utcMonths: utcMonths,
36106         utcYear: utcYear,
36107         utcYears: utcYears,
36108         timeFormatDefaultLocale: defaultLocale$1,
36109         get timeFormat () { return timeFormat; },
36110         get timeParse () { return timeParse; },
36111         get utcFormat () { return utcFormat; },
36112         get utcParse () { return utcParse; },
36113         timeFormatLocale: formatLocale$1,
36114         isoFormat: formatIso,
36115         isoParse: parseIso,
36116         now: now$1,
36117         timer: timer$1,
36118         timerFlush: timerFlush$1,
36119         timeout: timeout$3,
36120         interval: interval$3,
36121         transition: transition,
36122         active: active,
36123         interrupt: interrupt,
36124         voronoi: voronoi,
36125         zoom: zoom$1,
36126         zoomTransform: transform$1,
36127         zoomIdentity: identity$9
36128 });
36129
36130 /*
36131     Bypasses features of D3's default projection stream pipeline that are unnecessary:
36132     * Antimeridian clipping
36133     * Spherical rotation
36134     * Resampling
36135 */
36136 function geoRawMercator() {
36137     var project = mercatorRaw,
36138         k = 512 / Math.PI, // scale
36139         x = 0, y = 0, // translate
36140         clipExtent = [[0, 0], [0, 0]];
36141
36142
36143     function projection(point) {
36144         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
36145         return [point[0] * k + x, y - point[1] * k];
36146     }
36147
36148
36149     projection.invert = function(point) {
36150         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
36151         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
36152     };
36153
36154
36155     projection.scale = function(_) {
36156         if (!arguments.length) return k;
36157         k = +_;
36158         return projection;
36159     };
36160
36161
36162     projection.translate = function(_) {
36163         if (!arguments.length) return [x, y];
36164         x = +_[0];
36165         y = +_[1];
36166         return projection;
36167     };
36168
36169
36170     projection.clipExtent = function(_) {
36171         if (!arguments.length) return clipExtent;
36172         clipExtent = _;
36173         return projection;
36174     };
36175
36176
36177     projection.transform = function(_) {
36178         if (!arguments.length) return identity$9.translate(x, y).scale(k);
36179         x = +_.x;
36180         y = +_.y;
36181         k = +_.k;
36182         return projection;
36183     };
36184
36185
36186     projection.stream = transform({
36187         point: function(x, y) {
36188             x = projection([x, y]);
36189             this.stream.point(x[0], x[1]);
36190         }
36191     }).stream;
36192
36193
36194     return projection;
36195 }
36196
36197 function osmNode() {
36198     if (!(this instanceof osmNode)) {
36199         return (new osmNode()).initialize(arguments);
36200     } else if (arguments.length) {
36201         this.initialize(arguments);
36202     }
36203 }
36204
36205 osmEntity$$1.node = osmNode;
36206
36207 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36208
36209 lodash.extend(osmNode.prototype, {
36210
36211     type: 'node',
36212
36213
36214     extent: function() {
36215         return new geoExtent$$1(this.loc);
36216     },
36217
36218
36219     geometry: function(graph) {
36220         return graph.transient(this, 'geometry', function() {
36221             return graph.isPoi(this) ? 'point' : 'vertex';
36222         });
36223     },
36224
36225
36226     move: function(loc) {
36227         return this.update({loc: loc});
36228     },
36229
36230
36231     isDegenerate: function() {
36232         return !(
36233             Array.isArray(this.loc) && this.loc.length === 2 &&
36234             this.loc[0] >= -180 && this.loc[0] <= 180 &&
36235             this.loc[1] >= -90 && this.loc[1] <= 90
36236         );
36237     },
36238
36239
36240     isEndpoint: function(resolver) {
36241         return resolver.transient(this, 'isEndpoint', function() {
36242             var id = this.id;
36243             return resolver.parentWays(this).filter(function(parent) {
36244                 return !parent.isClosed() && !!parent.affix(id);
36245             }).length > 0;
36246         });
36247     },
36248
36249
36250     isConnected: function(resolver) {
36251         return resolver.transient(this, 'isConnected', function() {
36252             var parents = resolver.parentWays(this);
36253
36254             // vertex is connected to multiple parent ways
36255             if (parents.length > 1) {
36256                 return true;
36257
36258             } else if (parents.length === 1) {
36259                 var way = parents[0],
36260                     nodes = way.nodes.slice();
36261                 if (way.isClosed()) { nodes.pop(); }  // ignore connecting node if closed
36262
36263                 // return true if vertex appears multiple times (way is self intersecting)
36264                 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
36265             }
36266
36267             return false;
36268         });
36269     },
36270
36271
36272     isIntersection: function(resolver) {
36273         return resolver.transient(this, 'isIntersection', function() {
36274             return resolver.parentWays(this).filter(function(parent) {
36275                 return (parent.tags.highway ||
36276                     parent.tags.waterway ||
36277                     parent.tags.railway ||
36278                     parent.tags.aeroway) &&
36279                     parent.geometry(resolver) === 'line';
36280             }).length > 1;
36281         });
36282     },
36283
36284
36285     isHighwayIntersection: function(resolver) {
36286         return resolver.transient(this, 'isHighwayIntersection', function() {
36287             return resolver.parentWays(this).filter(function(parent) {
36288                 return parent.tags.highway && parent.geometry(resolver) === 'line';
36289             }).length > 1;
36290         });
36291     },
36292
36293
36294     isOnAddressLine: function(resolver) {
36295         return resolver.transient(this, 'isOnAddressLine', function() {
36296             return resolver.parentWays(this).filter(function(parent) {
36297                 return parent.tags.hasOwnProperty('addr:interpolation') &&
36298                     parent.geometry(resolver) === 'line';
36299             }).length > 0;
36300         });
36301     },
36302
36303
36304     asJXON: function(changeset_id) {
36305         var r = {
36306             node: {
36307                 '@id': this.osmId(),
36308                 '@lon': this.loc[0],
36309                 '@lat': this.loc[1],
36310                 '@version': (this.version || 0),
36311                 tag: lodash.map(this.tags, function(v, k) {
36312                     return { keyAttributes: { k: k, v: v } };
36313                 })
36314             }
36315         };
36316         if (changeset_id) r.node['@changeset'] = changeset_id;
36317         return r;
36318     },
36319
36320
36321     asGeoJSON: function() {
36322         return {
36323             type: 'Point',
36324             coordinates: this.loc
36325         };
36326     }
36327 });
36328
36329 /*
36330   Order the nodes of a way in reverse order and reverse any direction dependent tags
36331   other than `oneway`. (We assume that correcting a backwards oneway is the primary
36332   reason for reversing a way.)
36333
36334   The following transforms are performed:
36335
36336     Keys:
36337           *:right=* ⟺ *:left=*
36338         *:forward=* ⟺ *:backward=*
36339        direction=up ⟺ direction=down
36340          incline=up ⟺ incline=down
36341             *=right ⟺ *=left
36342
36343     Relation members:
36344        role=forward ⟺ role=backward
36345          role=north ⟺ role=south
36346           role=east ⟺ role=west
36347
36348    In addition, numeric-valued `incline` tags are negated.
36349
36350    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36351    or adjusted tags that don't seem to be used in practice were omitted.
36352
36353    Also, each node on the way is examined for its own tags and the following transformations are performed
36354    in order to ensure associated nodes (eg a Stop Sign) is also reversed
36355
36356     Node Keys:
36357         direction=forward ⟺ direction=backward
36358         direction=left ⟺ direction=right
36359         *:forward=* ⟺ *:backward=*
36360         *:left=* ⟺ *:right=*
36361
36362    References:
36363       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36364       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36365       http://wiki.openstreetmap.org/wiki/Key:incline
36366       http://wiki.openstreetmap.org/wiki/Route#Members
36367       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36368       http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36369       http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36370  */
36371 function actionReverse(wayId, options) {
36372     var replacements = [
36373             [/:right$/, ':left'], [/:left$/, ':right'],
36374             [/:forward$/, ':backward'], [/:backward$/, ':forward']
36375         ],
36376         numeric = /^([+\-]?)(?=[\d.])/,
36377         roleReversals = {
36378             forward: 'backward',
36379             backward: 'forward',
36380             north: 'south',
36381             south: 'north',
36382             east: 'west',
36383             west: 'east'
36384         };
36385
36386
36387     function reverseKey(key) {
36388         for (var i = 0; i < replacements.length; ++i) {
36389             var replacement = replacements[i];
36390             if (replacement[0].test(key)) {
36391                 return key.replace(replacement[0], replacement[1]);
36392             }
36393         }
36394         return key;
36395     }
36396
36397
36398     function reverseValue(key, value) {
36399         if (key === 'incline' && numeric.test(value)) {
36400             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36401         } else if (key === 'incline' || key === 'direction') {
36402             return {up: 'down', down: 'up'}[value] || value;
36403         } else if (options && options.reverseOneway && key === 'oneway') {
36404             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36405         } else {
36406             return {left: 'right', right: 'left'}[value] || value;
36407         }
36408     }
36409
36410
36411     function reverseDirectionTags(node) {
36412         // Update the direction based tags as appropriate then return an updated node
36413         return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36414             // See if this is a direction tag and reverse (or use existing value if not recognised)
36415             if (tagKey === 'direction') {
36416                 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36417             } else {
36418                 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36419                 // This will pass through other tags unchanged
36420                 acc[reverseKey(tagKey)] = tagValue;
36421             }
36422             return acc;
36423         }, {})});
36424     }
36425
36426
36427     function reverseTagsOnNodes(graph, nodeIds) {
36428         // Reverse the direction of appropriate tags attached to the nodes (#3076)
36429         return lodash(nodeIds)
36430             // Get each node from the graph
36431             .map(function(nodeId) { return graph.entity(nodeId);})
36432             // Check tags on the node, if there aren't any, we can skip
36433             .filter(function(existingNode) { return existingNode.tags !== undefined;})
36434             // Get a new version of each node with the appropriate tags reversed
36435             .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36436             // Chain together consecutive updates to the graph for each updated node and return
36437             .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36438     }
36439
36440
36441     return function(graph) {
36442         var way = graph.entity(wayId),
36443             nodes = way.nodes.slice().reverse(),
36444             tags = {}, key, role;
36445
36446         for (key in way.tags) {
36447             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36448         }
36449
36450         graph.parentRelations(way).forEach(function(relation) {
36451             relation.members.forEach(function(member, index) {
36452                 if (member.id === way.id && (role = roleReversals[member.role])) {
36453                     relation = relation.updateMember({role: role}, index);
36454                     graph = graph.replace(relation);
36455                 }
36456             });
36457         });
36458
36459         // Reverse any associated directions on nodes on the way and then replace
36460         // the way itself with the reversed node ids and updated way tags
36461         return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36462     };
36463 }
36464
36465 // For fixing up rendering of multipolygons with tags on the outer member.
36466 // https://github.com/openstreetmap/iD/issues/613
36467 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36468     if (entity.type !== 'way')
36469         return false;
36470
36471     var parents = graph.parentRelations(entity);
36472     if (parents.length !== 1)
36473         return false;
36474
36475     var parent = parents[0];
36476     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36477         return false;
36478
36479     var members = parent.members, member;
36480     for (var i = 0; i < members.length; i++) {
36481         member = members[i];
36482         if (member.id === entity.id && member.role && member.role !== 'outer')
36483             return false; // Not outer member
36484         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36485             return false; // Not a simple multipolygon
36486     }
36487
36488     return parent;
36489 }
36490
36491
36492 function osmSimpleMultipolygonOuterMember(entity, graph) {
36493     if (entity.type !== 'way')
36494         return false;
36495
36496     var parents = graph.parentRelations(entity);
36497     if (parents.length !== 1)
36498         return false;
36499
36500     var parent = parents[0];
36501     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36502         return false;
36503
36504     var members = parent.members, member, outerMember;
36505     for (var i = 0; i < members.length; i++) {
36506         member = members[i];
36507         if (!member.role || member.role === 'outer') {
36508             if (outerMember)
36509                 return false; // Not a simple multipolygon
36510             outerMember = member;
36511         }
36512     }
36513
36514     return outerMember && graph.hasEntity(outerMember.id);
36515 }
36516
36517
36518 // Join `array` into sequences of connecting ways.
36519 //
36520 // Segments which share identical start/end nodes will, as much as possible,
36521 // be connected with each other.
36522 //
36523 // The return value is a nested array. Each constituent array contains elements
36524 // of `array` which have been determined to connect. Each consitituent array
36525 // also has a `nodes` property whose value is an ordered array of member nodes,
36526 // with appropriate order reversal and start/end coordinate de-duplication.
36527 //
36528 // Members of `array` must have, at minimum, `type` and `id` properties.
36529 // Thus either an array of `osmWay`s or a relation member array may be
36530 // used.
36531 //
36532 // If an member has a `tags` property, its tags will be reversed via
36533 // `actionReverse` in the output.
36534 //
36535 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36536 // false) and non-way members are ignored.
36537 //
36538 function osmJoinWays(array, graph) {
36539     var joined = [], member, current, nodes, first, last, i, how, what;
36540
36541     array = array.filter(function(member) {
36542         return member.type === 'way' && graph.hasEntity(member.id);
36543     });
36544
36545     function resolve(member) {
36546         return graph.childNodes(graph.entity(member.id));
36547     }
36548
36549     function reverse(member) {
36550         return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36551     }
36552
36553     while (array.length) {
36554         member = array.shift();
36555         current = [member];
36556         current.nodes = nodes = resolve(member).slice();
36557         joined.push(current);
36558
36559         while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36560             first = lodash.first(nodes);
36561             last  = lodash.last(nodes);
36562
36563             for (i = 0; i < array.length; i++) {
36564                 member = array[i];
36565                 what = resolve(member);
36566
36567                 if (last === lodash.first(what)) {
36568                     how  = nodes.push;
36569                     what = what.slice(1);
36570                     break;
36571                 } else if (last === lodash.last(what)) {
36572                     how  = nodes.push;
36573                     what = what.slice(0, -1).reverse();
36574                     member = reverse(member);
36575                     break;
36576                 } else if (first === lodash.last(what)) {
36577                     how  = nodes.unshift;
36578                     what = what.slice(0, -1);
36579                     break;
36580                 } else if (first === lodash.first(what)) {
36581                     how  = nodes.unshift;
36582                     what = what.slice(1).reverse();
36583                     member = reverse(member);
36584                     break;
36585                 } else {
36586                     what = how = null;
36587                 }
36588             }
36589
36590             if (!what)
36591                 break; // No more joinable ways.
36592
36593             how.apply(current, [member]);
36594             how.apply(nodes, what);
36595
36596             array.splice(i, 1);
36597         }
36598     }
36599
36600     return joined;
36601 }
36602
36603 function osmRelation() {
36604     if (!(this instanceof osmRelation)) {
36605         return (new osmRelation()).initialize(arguments);
36606     } else if (arguments.length) {
36607         this.initialize(arguments);
36608     }
36609 }
36610
36611
36612 osmEntity$$1.relation = osmRelation;
36613
36614 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36615
36616
36617 osmRelation.creationOrder = function(a, b) {
36618     var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36619     var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36620
36621     if (aId < 0 || bId < 0) return aId - bId;
36622     return bId - aId;
36623 };
36624
36625
36626 lodash.extend(osmRelation.prototype, {
36627     type: 'relation',
36628     members: [],
36629
36630
36631     copy: function(resolver, copies) {
36632         if (copies[this.id])
36633             return copies[this.id];
36634
36635         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36636
36637         var members = this.members.map(function(member) {
36638             return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36639         });
36640
36641         copy = copy.update({members: members});
36642         copies[this.id] = copy;
36643
36644         return copy;
36645     },
36646
36647
36648     extent: function(resolver, memo) {
36649         return resolver.transient(this, 'extent', function() {
36650             if (memo && memo[this.id]) return geoExtent$$1();
36651             memo = memo || {};
36652             memo[this.id] = true;
36653
36654             var extent$$1 = geoExtent$$1();
36655             for (var i = 0; i < this.members.length; i++) {
36656                 var member = resolver.hasEntity(this.members[i].id);
36657                 if (member) {
36658                     extent$$1._extend(member.extent(resolver, memo));
36659                 }
36660             }
36661             return extent$$1;
36662         });
36663     },
36664
36665
36666     geometry: function(graph) {
36667         return graph.transient(this, 'geometry', function() {
36668             return this.isMultipolygon() ? 'area' : 'relation';
36669         });
36670     },
36671
36672
36673     isDegenerate: function() {
36674         return this.members.length === 0;
36675     },
36676
36677
36678     // Return an array of members, each extended with an 'index' property whose value
36679     // is the member index.
36680     indexedMembers: function() {
36681         var result = new Array(this.members.length);
36682         for (var i = 0; i < this.members.length; i++) {
36683             result[i] = lodash.extend({}, this.members[i], {index: i});
36684         }
36685         return result;
36686     },
36687
36688
36689     // Return the first member with the given role. A copy of the member object
36690     // is returned, extended with an 'index' property whose value is the member index.
36691     memberByRole: function(role) {
36692         for (var i = 0; i < this.members.length; i++) {
36693             if (this.members[i].role === role) {
36694                 return lodash.extend({}, this.members[i], {index: i});
36695             }
36696         }
36697     },
36698
36699
36700     // Return the first member with the given id. A copy of the member object
36701     // is returned, extended with an 'index' property whose value is the member index.
36702     memberById: function(id) {
36703         for (var i = 0; i < this.members.length; i++) {
36704             if (this.members[i].id === id) {
36705                 return lodash.extend({}, this.members[i], {index: i});
36706             }
36707         }
36708     },
36709
36710
36711     // Return the first member with the given id and role. A copy of the member object
36712     // is returned, extended with an 'index' property whose value is the member index.
36713     memberByIdAndRole: function(id, role) {
36714         for (var i = 0; i < this.members.length; i++) {
36715             if (this.members[i].id === id && this.members[i].role === role) {
36716                 return lodash.extend({}, this.members[i], {index: i});
36717             }
36718         }
36719     },
36720
36721
36722     addMember: function(member, index) {
36723         var members = this.members.slice();
36724         members.splice(index === undefined ? members.length : index, 0, member);
36725         return this.update({members: members});
36726     },
36727
36728
36729     updateMember: function(member, index) {
36730         var members = this.members.slice();
36731         members.splice(index, 1, lodash.extend({}, members[index], member));
36732         return this.update({members: members});
36733     },
36734
36735
36736     removeMember: function(index) {
36737         var members = this.members.slice();
36738         members.splice(index, 1);
36739         return this.update({members: members});
36740     },
36741
36742
36743     removeMembersWithID: function(id) {
36744         var members = lodash.reject(this.members, function(m) { return m.id === id; });
36745         return this.update({members: members});
36746     },
36747
36748
36749     // Wherever a member appears with id `needle.id`, replace it with a member
36750     // with id `replacement.id`, type `replacement.type`, and the original role,
36751     // unless a member already exists with that id and role. Return an updated
36752     // relation.
36753     replaceMember: function(needle, replacement) {
36754         if (!this.memberById(needle.id))
36755             return this;
36756
36757         var members = [];
36758
36759         for (var i = 0; i < this.members.length; i++) {
36760             var member = this.members[i];
36761             if (member.id !== needle.id) {
36762                 members.push(member);
36763             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36764                 members.push({id: replacement.id, type: replacement.type, role: member.role});
36765             }
36766         }
36767
36768         return this.update({members: members});
36769     },
36770
36771
36772     asJXON: function(changeset_id) {
36773         var r = {
36774             relation: {
36775                 '@id': this.osmId(),
36776                 '@version': this.version || 0,
36777                 member: lodash.map(this.members, function(member) {
36778                     return {
36779                         keyAttributes: {
36780                             type: member.type,
36781                             role: member.role,
36782                             ref: osmEntity$$1.id.toOSM(member.id)
36783                         }
36784                     };
36785                 }),
36786                 tag: lodash.map(this.tags, function(v, k) {
36787                     return { keyAttributes: { k: k, v: v } };
36788                 })
36789             }
36790         };
36791         if (changeset_id) r.relation['@changeset'] = changeset_id;
36792         return r;
36793     },
36794
36795
36796     asGeoJSON: function(resolver) {
36797         return resolver.transient(this, 'GeoJSON', function () {
36798             if (this.isMultipolygon()) {
36799                 return {
36800                     type: 'MultiPolygon',
36801                     coordinates: this.multipolygon(resolver)
36802                 };
36803             } else {
36804                 return {
36805                     type: 'FeatureCollection',
36806                     properties: this.tags,
36807                     features: this.members.map(function (member) {
36808                         return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36809                     })
36810                 };
36811             }
36812         });
36813     },
36814
36815
36816     area: function(resolver) {
36817         return resolver.transient(this, 'area', function() {
36818             return area(this.asGeoJSON(resolver));
36819         });
36820     },
36821
36822
36823     isMultipolygon: function() {
36824         return this.tags.type === 'multipolygon';
36825     },
36826
36827
36828     isComplete: function(resolver) {
36829         for (var i = 0; i < this.members.length; i++) {
36830             if (!resolver.hasEntity(this.members[i].id)) {
36831                 return false;
36832             }
36833         }
36834         return true;
36835     },
36836
36837
36838     isRestriction: function() {
36839         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36840     },
36841
36842
36843     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36844     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36845     //
36846     // This corresponds to the structure needed for rendering a multipolygon path using a
36847     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36848     //
36849     // In the case of invalid geometries, this function will still return a result which
36850     // includes the nodes of all way members, but some Nds may be unclosed and some inner
36851     // rings not matched with the intended outer ring.
36852     //
36853     multipolygon: function(resolver) {
36854         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36855             inners = this.members.filter(function(m) { return 'inner' === m.role; });
36856
36857         outers = osmJoinWays(outers, resolver);
36858         inners = osmJoinWays(inners, resolver);
36859
36860         outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36861         inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36862
36863         var result = outers.map(function(o) {
36864             // Heuristic for detecting counterclockwise winding order. Assumes
36865             // that OpenStreetMap polygons are not hemisphere-spanning.
36866             return [area({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36867         });
36868
36869         function findOuter(inner) {
36870             var o, outer;
36871
36872             for (o = 0; o < outers.length; o++) {
36873                 outer = outers[o];
36874                 if (geoPolygonContainsPolygon(outer, inner))
36875                     return o;
36876             }
36877
36878             for (o = 0; o < outers.length; o++) {
36879                 outer = outers[o];
36880                 if (geoPolygonIntersectsPolygon(outer, inner, false))
36881                     return o;
36882             }
36883         }
36884
36885         for (var i = 0; i < inners.length; i++) {
36886             var inner = inners[i];
36887
36888             if (area({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36889                 inner = inner.reverse();
36890             }
36891
36892             var o = findOuter(inners[i]);
36893             if (o !== undefined)
36894                 result[o].push(inners[i]);
36895             else
36896                 result.push([inners[i]]); // Invalid geometry
36897         }
36898
36899         return result;
36900     }
36901 });
36902
36903 function osmLanes(entity) {
36904     if (entity.type !== 'way') return null;
36905     if (!entity.tags.highway) return null;
36906
36907     var tags = entity.tags;
36908     var isOneWay = entity.isOneWay();
36909     var laneCount = getLaneCount(tags, isOneWay);
36910     var maxspeed = parseMaxspeed(tags);
36911
36912     var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36913     var forward = laneDirections.forward;
36914     var backward = laneDirections.backward;
36915     var bothways = laneDirections.bothways;
36916
36917     // parse the piped string 'x|y|z' format
36918     var turnLanes = {};
36919     turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36920     turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36921     turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36922
36923     var maxspeedLanes = {};
36924     maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36925     maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36926     maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36927
36928     var psvLanes = {};
36929     psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36930     psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36931     psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36932
36933     var busLanes = {};
36934     busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36935     busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36936     busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36937
36938     var taxiLanes = {};
36939     taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36940     taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36941     taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36942
36943     var hovLanes = {};
36944     hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36945     hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36946     hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36947
36948     var hgvLanes = {};
36949     hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36950     hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36951     hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36952
36953     var bicyclewayLanes = {};
36954     bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36955     bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36956     bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36957
36958     var lanesObj = {
36959         forward: [],
36960         backward: [],
36961         unspecified: []
36962     };
36963
36964     // map forward/backward/unspecified of each lane type to lanesObj
36965     mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36966     mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36967     mapToLanesObj(lanesObj, psvLanes, 'psv');
36968     mapToLanesObj(lanesObj, busLanes, 'bus');
36969     mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36970     mapToLanesObj(lanesObj, hovLanes, 'hov');
36971     mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36972     mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36973
36974     return {
36975         metadata: {
36976             count: laneCount,
36977             oneway: isOneWay,
36978             forward: forward,
36979             backward: backward,
36980             bothways: bothways,
36981             turnLanes: turnLanes,
36982             maxspeed: maxspeed,
36983             maxspeedLanes: maxspeedLanes,
36984             psvLanes: psvLanes,
36985             busLanes: busLanes,
36986             taxiLanes: taxiLanes,
36987             hovLanes: hovLanes,
36988             hgvLanes: hgvLanes,
36989             bicyclewayLanes: bicyclewayLanes
36990         },
36991         lanes: lanesObj
36992     };
36993 }
36994
36995
36996 function getLaneCount(tags, isOneWay) {
36997     var count;
36998     if (tags.lanes) {
36999         count = parseInt(tags.lanes, 10);
37000         if (count > 0) {
37001             return count;
37002         }
37003     }
37004
37005
37006     switch (tags.highway) {
37007         case 'trunk':
37008         case 'motorway':
37009             count = isOneWay ? 2 : 4;
37010             break;
37011         default:
37012             count = isOneWay ? 1 : 2;
37013             break;
37014     }
37015
37016     return count;
37017 }
37018
37019
37020 function parseMaxspeed(tags) {
37021     var maxspeed = tags.maxspeed;
37022     if (lodash.isNumber(maxspeed)) return maxspeed;
37023     if (lodash.isString(maxspeed)) {
37024         maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
37025         if (!maxspeed) return;
37026         return parseInt(maxspeed, 10);
37027     }
37028 }
37029
37030
37031 function parseLaneDirections(tags, isOneWay, laneCount) {
37032     var forward = parseInt(tags['lanes:forward'], 10);
37033     var backward = parseInt(tags['lanes:backward'], 10);
37034     var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37035
37036     if (parseInt(tags.oneway, 10) === -1) {
37037         forward = 0;
37038         bothways = 0;
37039         backward = laneCount;
37040     }
37041     else if (isOneWay) {
37042         forward = laneCount;
37043         bothways = 0;
37044         backward = 0;
37045     }
37046     else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
37047         backward = Math.floor((laneCount - bothways) / 2);
37048         forward = laneCount - bothways - backward;
37049     }
37050     else if (lodash.isNaN(forward)) {
37051         if (backward > laneCount - bothways) {
37052             backward = laneCount - bothways;
37053         }
37054         forward = laneCount - bothways - backward;
37055     }
37056     else if (lodash.isNaN(backward)) {
37057         if (forward > laneCount - bothways) {
37058             forward = laneCount - bothways;
37059         }
37060         backward = laneCount - bothways - forward;
37061     }
37062     return {
37063         forward: forward,
37064         backward: backward,
37065         bothways: bothways
37066     };
37067 }
37068
37069
37070 function parseTurnLanes(tag){
37071     if (!tag) return;
37072
37073     var validValues = [
37074         'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
37075         'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
37076     ];
37077
37078     return tag.split('|')
37079         .map(function (s) {
37080             if (s === '') s = 'none';
37081             return s.split(';')
37082                 .map(function (d) {
37083                     return validValues.indexOf(d) === -1 ? 'unknown': d;
37084                 });
37085         });
37086 }
37087
37088
37089 function parseMaxspeedLanes(tag, maxspeed) {
37090     if (!tag) return;
37091
37092     return tag.split('|')
37093         .map(function (s) {
37094             if (s === 'none') return s;
37095             var m = parseInt(s, 10);
37096             if (s === '' || m === maxspeed) return null;
37097             return lodash.isNaN(m) ? 'unknown': m;
37098         });
37099 }
37100
37101
37102 function parseMiscLanes(tag) {
37103     if (!tag) return;
37104
37105     var validValues = [
37106         'yes', 'no', 'designated'
37107     ];
37108
37109     return tag.split('|')
37110         .map(function (s) {
37111             if (s === '') s = 'no';
37112             return validValues.indexOf(s) === -1 ? 'unknown': s;
37113         });
37114 }
37115
37116
37117 function parseBicycleWay(tag) {
37118     if (!tag) return;
37119
37120     var validValues = [
37121         'yes', 'no', 'designated', 'lane'
37122     ];
37123
37124     return tag.split('|')
37125         .map(function (s) {
37126             if (s === '') s = 'no';
37127             return validValues.indexOf(s) === -1 ? 'unknown': s;
37128         });
37129 }
37130
37131
37132 function mapToLanesObj(lanesObj, data, key) {
37133     if (data.forward) data.forward.forEach(function(l, i) {
37134         if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37135         lanesObj.forward[i][key] = l;
37136     });
37137     if (data.backward) data.backward.forEach(function(l, i) {
37138         if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37139         lanesObj.backward[i][key] = l;
37140     });
37141     if (data.unspecified) data.unspecified.forEach(function(l, i) {
37142         if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37143         lanesObj.unspecified[i][key] = l;
37144     });
37145 }
37146
37147 var translations = Object.create(null);
37148
37149 var currentLocale = 'en';
37150 var textDirection = 'ltr';
37151
37152 function setLocale(_) {
37153     if (translations[_] !== undefined) {
37154         currentLocale = _;
37155     } else if (translations[_.split('-')[0]]) {
37156         currentLocale = _.split('-')[0];
37157     }
37158 }
37159
37160 function addTranslation(id, value) {
37161     translations[id] = value;
37162 }
37163
37164 /**
37165  * Given a string identifier, try to find that string in the current
37166  * language, and return it.
37167  *
37168  * @param {string} s string identifier
37169  * @returns {string?} locale string
37170  */
37171 function t(s, o, loc) {
37172     loc = loc || currentLocale;
37173
37174     var path = s.split('.').reverse();
37175     var rep = translations[loc];
37176
37177     while (rep !== undefined && path.length) rep = rep[path.pop()];
37178
37179     if (rep !== undefined) {
37180         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
37181         return rep;
37182     }
37183
37184     if (loc !== 'en') {
37185         return t(s, o, 'en');
37186     }
37187
37188     if (o && 'default' in o) {
37189         return o.default;
37190     }
37191
37192     var missing = 'Missing ' + loc + ' translation: ' + s;
37193     if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
37194
37195     return missing;
37196 }
37197
37198 /**
37199  * Given string 'ltr' or 'rtl', save that setting
37200  *
37201  * @param {string} s ltr or rtl
37202  */
37203
37204 function setTextDirection(dir) {
37205     textDirection = dir;
37206 }
37207
37208 var detected;
37209
37210 function utilDetect(force) {
37211     if (detected && !force) return detected;
37212     detected = {};
37213
37214     var ua = navigator.userAgent,
37215         m = null;
37216
37217     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
37218     if (m !== null) {
37219         detected.browser = m[1];
37220         detected.version = m[2];
37221     }
37222     if (!detected.browser) {
37223         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
37224         if (m !== null) {
37225             detected.browser = 'msie';
37226             detected.version = m[1];
37227         }
37228     }
37229     if (!detected.browser) {
37230         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
37231         if (m !== null) {
37232             detected.browser = 'Opera';
37233             detected.version = m[2];
37234         }
37235     }
37236     if (!detected.browser) {
37237         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
37238         if (m !== null) {
37239             detected.browser = m[1];
37240             detected.version = m[2];
37241             m = ua.match(/version\/([\.\d]+)/i);
37242             if (m !== null) detected.version = m[1];
37243         }
37244     }
37245     if (!detected.browser) {
37246         detected.browser = navigator.appName;
37247         detected.version = navigator.appVersion;
37248     }
37249
37250     // keep major.minor version only..
37251     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37252
37253     if (detected.browser.toLowerCase() === 'msie') {
37254         detected.ie = true;
37255         detected.browser = 'Internet Explorer';
37256         detected.support = parseFloat(detected.version) >= 11;
37257     } else {
37258         detected.ie = false;
37259         detected.support = true;
37260     }
37261
37262     // Added due to incomplete svg style support. See #715
37263     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37264
37265     detected.locale = (navigator.language || navigator.userLanguage || 'en-US');
37266     detected.language = detected.locale.split('-')[0];
37267
37268     // Search `navigator.languages` for a better locale.. Prefer the first language,
37269     // unless the second language is a culture-specific version of the first one, see #3842
37270     if (navigator.languages && navigator.languages.length > 0) {
37271         var code0 = navigator.languages[0],
37272             parts0 = code0.split('-');
37273
37274         detected.locale = code0;
37275         detected.language = parts0[0];
37276
37277         if (navigator.languages.length > 1 && parts0.length === 1) {
37278             var code1 = navigator.languages[1],
37279                 parts1 = code1.split('-');
37280
37281             if (parts1[0] === parts0[0]) {
37282                 detected.locale = code1;
37283             }
37284         }
37285     }
37286
37287     // Loaded locale is stored in currentLocale
37288     // return that instead (except in the situation where 'en' might override 'en-US')
37289     var loadedLocale = currentLocale || 'en';
37290     if (loadedLocale !== 'en') {
37291         detected.locale = loadedLocale;
37292         detected.language = detected.locale.split('-')[0];
37293     }
37294
37295     // detect text direction
37296     var q = utilStringQs(window.location.hash.substring(1));
37297     var lang = dataLocales[detected.locale];
37298     if ((lang && lang.rtl) || q.hasOwnProperty('rtl')) {
37299         detected.textDirection = 'rtl';
37300     } else {
37301         detected.textDirection = 'ltr';
37302     }
37303     setTextDirection(detected.textDirection);
37304
37305     detected.host = window.location && (window.location.origin + window.location.pathname);
37306
37307     detected.filedrop = (window.FileReader && 'ondrop' in window);
37308
37309     function nav(x) {
37310         return navigator.userAgent.indexOf(x) !== -1;
37311     }
37312
37313     if (nav('Win')) {
37314         detected.os = 'win';
37315         detected.platform = 'Windows';
37316     }
37317     else if (nav('Mac')) {
37318         detected.os = 'mac';
37319         detected.platform = 'Macintosh';
37320     }
37321     else if (nav('X11') || nav('Linux')) {
37322         detected.os = 'linux';
37323         detected.platform = 'Linux';
37324     }
37325     else {
37326         detected.os = 'win';
37327         detected.platform = 'Unknown';
37328     }
37329
37330     return detected;
37331 }
37332
37333 var remove$1 = removeDiacritics;
37334
37335 var replacementList = [
37336   {
37337     base: ' ',
37338     chars: "\u00A0",
37339   }, {
37340     base: '0',
37341     chars: "\u07C0",
37342   }, {
37343     base: 'A',
37344     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",
37345   }, {
37346     base: 'AA',
37347     chars: "\uA732",
37348   }, {
37349     base: 'AE',
37350     chars: "\u00C6\u01FC\u01E2",
37351   }, {
37352     base: 'AO',
37353     chars: "\uA734",
37354   }, {
37355     base: 'AU',
37356     chars: "\uA736",
37357   }, {
37358     base: 'AV',
37359     chars: "\uA738\uA73A",
37360   }, {
37361     base: 'AY',
37362     chars: "\uA73C",
37363   }, {
37364     base: 'B',
37365     chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37366   }, {
37367     base: 'C',
37368     chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37369   }, {
37370     base: 'D',
37371     chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37372   }, {
37373     base: 'Dh',
37374     chars: "\u00D0",
37375   }, {
37376     base: 'DZ',
37377     chars: "\u01F1\u01C4",
37378   }, {
37379     base: 'Dz',
37380     chars: "\u01F2\u01C5",
37381   }, {
37382     base: 'E',
37383     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",
37384   }, {
37385     base: 'F',
37386     chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37387   }, {
37388     base: 'G',
37389     chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37390   }, {
37391     base: 'H',
37392     chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37393   }, {
37394     base: 'I',
37395     chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37396   }, {
37397     base: 'J',
37398     chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37399   }, {
37400     base: 'K',
37401     chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37402   }, {
37403     base: 'L',
37404     chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37405   }, {
37406     base: 'LJ',
37407     chars: "\u01C7",
37408   }, {
37409     base: 'Lj',
37410     chars: "\u01C8",
37411   }, {
37412     base: 'M',
37413     chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37414   }, {
37415     base: 'N',
37416     chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37417   }, {
37418     base: 'NJ',
37419     chars: "\u01CA",
37420   }, {
37421     base: 'Nj',
37422     chars: "\u01CB",
37423   }, {
37424     base: 'O',
37425     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",
37426   }, {
37427     base: 'OE',
37428     chars: "\u0152",
37429   }, {
37430     base: 'OI',
37431     chars: "\u01A2",
37432   }, {
37433     base: 'OO',
37434     chars: "\uA74E",
37435   }, {
37436     base: 'OU',
37437     chars: "\u0222",
37438   }, {
37439     base: 'P',
37440     chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37441   }, {
37442     base: 'Q',
37443     chars: "\u24C6\uFF31\uA756\uA758\u024A",
37444   }, {
37445     base: 'R',
37446     chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37447   }, {
37448     base: 'S',
37449     chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37450   }, {
37451     base: 'T',
37452     chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37453   }, {
37454     base: 'Th',
37455     chars: "\u00DE",
37456   }, {
37457     base: 'TZ',
37458     chars: "\uA728",
37459   }, {
37460     base: 'U',
37461     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",
37462   }, {
37463     base: 'V',
37464     chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37465   }, {
37466     base: 'VY',
37467     chars: "\uA760",
37468   }, {
37469     base: 'W',
37470     chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37471   }, {
37472     base: 'X',
37473     chars: "\u24CD\uFF38\u1E8A\u1E8C",
37474   }, {
37475     base: 'Y',
37476     chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37477   }, {
37478     base: 'Z',
37479     chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37480   }, {
37481     base: 'a',
37482     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",
37483   }, {
37484     base: 'aa',
37485     chars: "\uA733",
37486   }, {
37487     base: 'ae',
37488     chars: "\u00E6\u01FD\u01E3",
37489   }, {
37490     base: 'ao',
37491     chars: "\uA735",
37492   }, {
37493     base: 'au',
37494     chars: "\uA737",
37495   }, {
37496     base: 'av',
37497     chars: "\uA739\uA73B",
37498   }, {
37499     base: 'ay',
37500     chars: "\uA73D",
37501   }, {
37502     base: 'b',
37503     chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37504   }, {
37505     base: 'c',
37506     chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37507   }, {
37508     base: 'd',
37509     chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37510   }, {
37511     base: 'dh',
37512     chars: "\u00F0",
37513   }, {
37514     base: 'dz',
37515     chars: "\u01F3\u01C6",
37516   }, {
37517     base: 'e',
37518     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",
37519   }, {
37520     base: 'f',
37521     chars: "\u24D5\uFF46\u1E1F\u0192",
37522   }, {
37523     base: 'ff',
37524     chars: "\uFB00",
37525   }, {
37526     base: 'fi',
37527     chars: "\uFB01",
37528   }, {
37529     base: 'fl',
37530     chars: "\uFB02",
37531   }, {
37532     base: 'ffi',
37533     chars: "\uFB03",
37534   }, {
37535     base: 'ffl',
37536     chars: "\uFB04",
37537   }, {
37538     base: 'g',
37539     chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37540   }, {
37541     base: 'h',
37542     chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37543   }, {
37544     base: 'hv',
37545     chars: "\u0195",
37546   }, {
37547     base: 'i',
37548     chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37549   }, {
37550     base: 'j',
37551     chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37552   }, {
37553     base: 'k',
37554     chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37555   }, {
37556     base: 'l',
37557     chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37558   }, {
37559     base: 'lj',
37560     chars: "\u01C9",
37561   }, {
37562     base: 'm',
37563     chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37564   }, {
37565     base: 'n',
37566     chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37567   }, {
37568     base: 'nj',
37569     chars: "\u01CC",
37570   }, {
37571     base: 'o',
37572     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",
37573   }, {
37574     base: 'oe',
37575     chars: "\u0153",
37576   }, {
37577     base: 'oi',
37578     chars: "\u01A3",
37579   }, {
37580     base: 'oo',
37581     chars: "\uA74F",
37582   }, {
37583     base: 'ou',
37584     chars: "\u0223",
37585   }, {
37586     base: 'p',
37587     chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37588   }, {
37589     base: 'q',
37590     chars: "\u24E0\uFF51\u024B\uA757\uA759",
37591   }, {
37592     base: 'r',
37593     chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37594   }, {
37595     base: 's',
37596     chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37597   }, {
37598     base: 'ss',
37599     chars: "\xDF",
37600   }, {
37601     base: 't',
37602     chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37603   }, {
37604     base: 'th',
37605     chars: "\u00FE",
37606   }, {
37607     base: 'tz',
37608     chars: "\uA729",
37609   }, {
37610     base: 'u',
37611     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",
37612   }, {
37613     base: 'v',
37614     chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37615   }, {
37616     base: 'vy',
37617     chars: "\uA761",
37618   }, {
37619     base: 'w',
37620     chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37621   }, {
37622     base: 'x',
37623     chars: "\u24E7\uFF58\u1E8B\u1E8D",
37624   }, {
37625     base: 'y',
37626     chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37627   }, {
37628     base: 'z',
37629     chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37630   }
37631 ];
37632
37633 var diacriticsMap = {};
37634 for (var i = 0; i < replacementList.length; i += 1) {
37635   var chars = replacementList[i].chars;
37636   for (var j = 0; j < chars.length; j += 1) {
37637     diacriticsMap[chars[j]] = replacementList[i].base;
37638   }
37639 }
37640
37641 function removeDiacritics(str) {
37642   return str.replace(/[^\u0000-\u007e]/g, function(c) {
37643     return diacriticsMap[c] || c;
37644   });
37645 }
37646
37647 // see https://github.com/openstreetmap/iD/pull/3707
37648 // https://gist.github.com/mapmeld/556b09ddec07a2044c76e1ef45f01c60
37649
37650 var chars$1 = {
37651     // madda above alef
37652     1570: { initial: 'آ‎', isolated: 'ﺁ', medial: 'ﺁ', final: 'ﺂ' },
37653
37654     // hamza above and below alef
37655     1571: { initial: 'أ', isolated: 'ﺃ', medial: '', final: 'ﺄ' },
37656     // 1572 is ؤ
37657     1573: { initial: 'إ', isolated: 'ﺇ', medial: '', final: 'ﺈ' },
37658     // 1574 is ئ
37659     1575: { initial: 'ا', isolated: 'ا', medial: '', final: 'ﺎ' },
37660     1576: { initial: 'ﺑ', isolated: 'ﺏ', medial: 'ﺒ', final: 'ﺐ' },
37661
37662     // 1577 ة
37663     1577: { initial: '', isolated: 'ة', medial: '', final: 'ﺔ' },
37664
37665     1578: { initial: 'ﺗ', isolated: 'ﺕ', medial: 'ﺘ', final: 'ﺖ' },
37666     1579: { initial: 'ﺛ', isolated: 'ﺙ', medial: 'ﺜ', final: 'ﺚ' },
37667     1580: { initial: 'ﺟ', isolated: 'ﺝ', medial: 'ﺠ', final: 'ﺞ' },
37668     1581: { initial: 'ﺣ', isolated: 'ﺡ', medial: 'ﺤ', final: 'ﺢ' },
37669     1582: { initial: 'ﺧ', isolated: 'ﺥ', medial: 'ﺨ', final: 'ﺦ' },
37670     1583: { initial: 'ﺩ', isolated: 'ﺩ', medial: '', final: 'ﺪ' },
37671     1584: { initial: 'ﺫ', isolated: 'ﺫ', medial: '', final: 'ﺬ' },
37672     1585: { initial: 'ﺭ', isolated: 'ﺭ', medial: '', final: 'ﺮ' },
37673     1586: { initial: 'ﺯ', isolated: 'ﺯ', medial: '', final: 'ﺰ' },
37674     1688: { initial: 'ﮊ', isolated: 'ﮊ', medial: '', final: 'ﮋ' },
37675     1587: { initial: 'ﺳ', isolated: 'ﺱ', medial: 'ﺴ', final: 'ﺲ' },
37676     1588: { initial: 'ﺷ', isolated: 'ﺵ', medial: 'ﺸ', final: 'ﺶ' },
37677     1589: { initial: 'ﺻ', isolated: 'ﺹ', medial: 'ﺼ', final: 'ﺺ' },
37678     1590: { initial: 'ﺿ', isolated: 'ﺽ', medial: 'ﻀ', final: 'ﺾ' },
37679     1591: { initial: 'ﻃ', isolated: 'ﻁ', medial: 'ﻄ', final: 'ﻂ' },
37680     1592: { initial: 'ﻇ', isolated: 'ﻅ', medial: 'ﻈ', final: 'ﻆ' },
37681     1593: { initial: 'ﻋ', isolated: 'ﻉ', medial: 'ﻌ', final: 'ﻊ' },
37682     1594: { initial: 'ﻏ', isolated: 'ﻍ', medial: 'ﻐ', final: 'ﻎ' },
37683
37684     // 1595 ػ - may be very rare
37685
37686     1601: { initial: 'ﻓ', isolated: 'ﻑ', medial: 'ﻔ', final: 'ﻒ' },
37687     1602: { initial: 'ﻗ', isolated: 'ﻕ', medial: 'ﻘ', final: 'ﻖ' },
37688     1604: { initial: 'ﻟ', isolated: 'ﻝ', medial: 'ﻠ', final: 'ﻞ' },
37689     1605: { initial: 'ﻣ', isolated: 'ﻡ', medial: 'ﻤ', final: 'ﻢ' },
37690     1606: { initial: 'ﻧ', isolated: 'ﻥ', medial: 'ﻨ', final: 'ﻦ' },
37691     1607: { initial: 'ﻫ', isolated: 'ﻩ', medial: 'ﻬ', final: 'ﻪ' },
37692     1608: { initial: 'ﻭ', isolated: 'ﻭ', medial: '', final: 'ﻮ' },
37693
37694     // 1609 ى
37695     1609: { initial: 'ﯨ', isolated: 'ﻯ', medial: 'ﯩ', final: 'ﻰ' },
37696     // 1610 ي
37697     1610: { initial: 'ﻳ', isolated: 'ﻱ', medial: 'ﻴ', final: 'ﻲ' },
37698
37699     // short vowel sounds / tashkil markings
37700
37701     1662: { initial: 'ﭘ', isolated: 'ﭖ', medial: 'ﭙ', final: 'ﭗ' },
37702
37703     1670: { initial: 'ﭼ', isolated: 'ﭺ', medial: 'ﭽ', final: 'ﭻ' },
37704     1603: { initial: 'ﻛ', isolated: 'ﻙ', medial: 'ﻜ', final: 'ﻚ' },
37705     1705: { initial: 'ﻛ', isolated: 'ﮎ', medial: 'ﻜ', final: 'ﮏ' },
37706     1711: { initial: 'ﮔ', isolated: 'ﮒ', medial: 'ﮕ', final: 'ﮓ' },
37707     1740: { initial: 'ﻳ', isolated: 'ﻯ', medial: 'ﻴ', final: 'ﻰ' },
37708     5000: { initial: 'ﻻ', isolated: 'ﻻ', medial: '', final: 'ﻼ' }
37709 };
37710
37711
37712 function fixArabicScriptTextForSvg(inputText) {
37713     var context = true;
37714     var ret = '';
37715     var rtlBuffer = [];
37716
37717     for (var i = 0, l = inputText.length; i < l; i++) {
37718         var code = inputText[i].charCodeAt(0);
37719         var nextCode = inputText[i + 1] ? inputText[i + 1].charCodeAt(0) : 0;
37720
37721         if (!chars$1[code]) {
37722             if (code === 32 && rtlBuffer.length) {
37723               // whitespace
37724               rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37725             } else {
37726               // non-RTL character
37727               ret += rtlBuffer.reverse().join('') + inputText[i];
37728               rtlBuffer = [];
37729             }
37730             continue;
37731         }
37732         if (context) {
37733             if (i === l - 1 || nextCode === 32) {
37734                 rtlBuffer.push(chars$1[code].isolated);
37735             } else {
37736                 // special case for لا
37737                 if (code === 1604 && nextCode === 1575) {
37738                     rtlBuffer.push(chars$1[5000].initial);
37739                     i++;
37740                     context = true;
37741                     continue;
37742                 }
37743                 rtlBuffer.push(chars$1[code].initial);
37744             }
37745         } else {
37746             if (i === l - 1 || nextCode === 32){
37747                 rtlBuffer.push(chars$1[code].final);
37748             } else {
37749                 // special case for ﻼ
37750                 if (code === 1604 && nextCode === 1575){
37751                     rtlBuffer.push(chars$1[5000].final);
37752                     i++;
37753                     context = true;
37754                     continue;
37755                 }
37756                 if (chars$1[code].medial === ''){
37757                     rtlBuffer.push(chars$1[code].final);
37758                 } else {
37759                     rtlBuffer.push(chars$1[code].medial);
37760                 }
37761             }
37762         }
37763         context = (chars$1[code].medial === '') || nextCode === 32;
37764     }
37765
37766     ret += rtlBuffer.reverse().join('');
37767     return ret;
37768 }
37769
37770 function utilTagText(entity) {
37771     return entries(entity.tags).map(function(e) {
37772         return e.key + '=' + e.value;
37773     }).join(', ');
37774 }
37775
37776
37777 function utilEntitySelector(ids) {
37778     return ids.length ? '.' + ids.join(',.') : 'nothing';
37779 }
37780
37781
37782 function utilEntityOrMemberSelector(ids, graph) {
37783     var s = utilEntitySelector(ids);
37784
37785     ids.forEach(function(id) {
37786         var entity = graph.hasEntity(id);
37787         if (entity && entity.type === 'relation') {
37788             entity.members.forEach(function(member) {
37789                 s += ',.' + member.id;
37790             });
37791         }
37792     });
37793
37794     return s;
37795 }
37796
37797
37798 function utilGetAllNodes(ids, graph) {
37799     var seen = {};
37800     var nodes = [];
37801     ids.forEach(getNodes);
37802     return nodes;
37803
37804     function getNodes(id) {
37805         if (seen[id]) return;
37806         seen[id] = true;
37807
37808         var entity = graph.hasEntity(id);
37809         if (!entity) return;
37810
37811         if (entity.type === 'node') {
37812             nodes.push(entity);
37813         } else if (entity.type === 'way') {
37814             entity.nodes.forEach(getNodes);
37815         } else {
37816             entity.members.map(function(member) { return member.id; }).forEach(getNodes);
37817         }
37818     }
37819 }
37820
37821
37822 function utilDisplayName(entity) {
37823     var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37824         name = entity.tags[localizedNameKey] || entity.tags.name || '',
37825         network = entity.tags.cycle_network || entity.tags.network;
37826
37827     if (!name && entity.tags.ref) {
37828         name = entity.tags.ref;
37829         if (network) {
37830             name = network + ' ' + name;
37831         }
37832     }
37833
37834     return name;
37835 }
37836
37837
37838 function utilDisplayNameForPath(entity) {
37839     var name = utilDisplayName(entity);
37840     var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
37841     var arabicRegex = /[\u0600-\u06FF]/g;
37842
37843     if (!isFirefox && name && arabicRegex.test(name)) {
37844         name = fixArabicScriptTextForSvg(name);
37845     }
37846
37847     return name;
37848 }
37849
37850
37851 function utilDisplayType(id) {
37852     return {
37853         n: t('inspector.node'),
37854         w: t('inspector.way'),
37855         r: t('inspector.relation')
37856     }[id.charAt(0)];
37857 }
37858
37859
37860 function utilStringQs(str) {
37861     return str.split('&').reduce(function(obj, pair){
37862         var parts = pair.split('=');
37863         if (parts.length === 2) {
37864             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37865         }
37866         return obj;
37867     }, {});
37868 }
37869
37870
37871 function utilQsString(obj, noencode) {
37872     function softEncode(s) {
37873       // encode everything except special characters used in certain hash parameters:
37874       // "/" in map states, ":", ",", {" and "}" in background
37875       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37876     }
37877     return Object.keys(obj).sort().map(function(key) {
37878         return encodeURIComponent(key) + '=' + (
37879             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37880     }).join('&');
37881 }
37882
37883
37884 function utilPrefixDOMProperty(property) {
37885     var prefixes = ['webkit', 'ms', 'moz', 'o'],
37886         i = -1,
37887         n = prefixes.length,
37888         s = document.body;
37889
37890     if (property in s)
37891         return property;
37892
37893     property = property.substr(0, 1).toUpperCase() + property.substr(1);
37894
37895     while (++i < n)
37896         if (prefixes[i] + property in s)
37897             return prefixes[i] + property;
37898
37899     return false;
37900 }
37901
37902
37903 function utilPrefixCSSProperty(property) {
37904     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37905         i = -1,
37906         n = prefixes.length,
37907         s = document.body.style;
37908
37909     if (property.toLowerCase() in s)
37910         return property.toLowerCase();
37911
37912     while (++i < n)
37913         if (prefixes[i] + property in s)
37914             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37915
37916     return false;
37917 }
37918
37919
37920 var transformProperty;
37921 function utilSetTransform(el, x, y, scale) {
37922     var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37923         translate = utilDetect().opera ?
37924             'translate('   + x + 'px,' + y + 'px)' :
37925             'translate3d(' + x + 'px,' + y + 'px,0)';
37926     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37927 }
37928
37929
37930 // Calculates Levenshtein distance between two strings
37931 // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
37932 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37933 function utilEditDistance(a, b) {
37934     a = remove$1(a.toLowerCase());
37935     b = remove$1(b.toLowerCase());
37936     if (a.length === 0) return b.length;
37937     if (b.length === 0) return a.length;
37938     var matrix = [];
37939     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37940     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37941     for (i = 1; i <= b.length; i++) {
37942         for (j = 1; j <= a.length; j++) {
37943             if (b.charAt(i-1) === a.charAt(j-1)) {
37944                 matrix[i][j] = matrix[i-1][j-1];
37945             } else {
37946                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37947                     Math.min(matrix[i][j-1] + 1, // insertion
37948                     matrix[i-1][j] + 1)); // deletion
37949             }
37950         }
37951     }
37952     return matrix[b.length][a.length];
37953 }
37954
37955
37956 // a d3.mouse-alike which
37957 // 1. Only works on HTML elements, not SVG
37958 // 2. Does not cause style recalculation
37959 function utilFastMouse(container) {
37960     var rect = container.getBoundingClientRect(),
37961         rectLeft = rect.left,
37962         rectTop = rect.top,
37963         clientLeft = +container.clientLeft,
37964         clientTop = +container.clientTop;
37965     if (textDirection === 'rtl') {
37966         rectLeft = 0;
37967     }
37968     return function(e) {
37969         return [
37970             e.clientX - rectLeft - clientLeft,
37971             e.clientY - rectTop - clientTop];
37972     };
37973 }
37974
37975
37976 /* eslint-disable no-proto */
37977 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37978 /* eslint-enable no-proto */
37979
37980
37981 function utilAsyncMap(inputs, func, callback) {
37982     var remaining = inputs.length,
37983         results = [],
37984         errors = [];
37985
37986     inputs.forEach(function(d, i) {
37987         func(d, function done(err, data) {
37988             errors[i] = err;
37989             results[i] = data;
37990             remaining--;
37991             if (!remaining) callback(errors, results);
37992         });
37993     });
37994 }
37995
37996
37997 // wraps an index to an interval [0..length-1]
37998 function utilWrap(index, length) {
37999     if (index < 0)
38000         index += Math.ceil(-index/length)*length;
38001     return index % length;
38002 }
38003
38004
38005 /**
38006  * a replacement for functor
38007  *
38008  * @param {*} value any value
38009  * @returns {Function} a function that returns that value or the value if it's a function
38010  */
38011 function utilFunctor(value) {
38012     if (typeof value === 'function') return value;
38013     return function() {
38014         return value;
38015     };
38016 }
38017
38018
38019 function utilNoAuto(selection$$1) {
38020     return selection$$1
38021         .attr('autocomplete', 'off')
38022         .attr('autocorrect', 'off')
38023         .attr('autocapitalize', 'off')
38024         .attr('spellcheck', 'false');
38025 }
38026
38027 // Like selection.property('value', ...), but avoids no-op value sets,
38028 // which can result in layout/repaint thrashing in some situations.
38029 function utilGetSetValue(selection, value) {
38030     function d3_selection_value(value) {
38031         function valueNull() {
38032             delete this.value;
38033         }
38034
38035         function valueConstant() {
38036             if (this.value !== value) {
38037                 this.value = value;
38038             }
38039         }
38040
38041         function valueFunction() {
38042             var x = value.apply(this, arguments);
38043             if (x == null) {
38044                 delete this.value;
38045             } else if (this.value !== x) {
38046                 this.value = x;
38047             }
38048         }
38049
38050         return value == null
38051             ? valueNull : (typeof value === 'function'
38052             ? valueFunction : valueConstant);
38053     }
38054
38055     if (arguments.length === 1) {
38056         return selection.property('value');
38057     }
38058
38059     return selection.each(d3_selection_value(value));
38060 }
38061
38062 // Copies a variable number of methods from source to target.
38063 function utilRebind(target, source) {
38064     var i = 1, n = arguments.length, method;
38065     while (++i < n) {
38066         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
38067     }
38068     return target;
38069 }
38070
38071 // Method is assumed to be a standard D3 getter-setter:
38072 // If passed with no arguments, gets the value.
38073 // If passed with arguments, sets the value and returns the target.
38074 function d3_rebind(target, source, method) {
38075     return function() {
38076         var value = method.apply(source, arguments);
38077         return value === source ? target : value;
38078     };
38079 }
38080
38081 // A per-domain session mutex backed by a cookie and dead man's
38082 // switch. If the session crashes, the mutex will auto-release
38083 // after 5 seconds.
38084
38085 function utilSessionMutex(name) {
38086     var mutex = {},
38087         intervalID;
38088
38089     function renew() {
38090         var expires = new Date();
38091         expires.setSeconds(expires.getSeconds() + 5);
38092         document.cookie = name + '=1; expires=' + expires.toUTCString();
38093     }
38094
38095     mutex.lock = function() {
38096         if (intervalID) return true;
38097         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
38098         if (cookie) return false;
38099         renew();
38100         intervalID = window.setInterval(renew, 4000);
38101         return true;
38102     };
38103
38104     mutex.unlock = function() {
38105         if (!intervalID) return;
38106         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
38107         clearInterval(intervalID);
38108         intervalID = null;
38109     };
38110
38111     mutex.locked = function() {
38112         return !!intervalID;
38113     };
38114
38115     return mutex;
38116 }
38117
38118 function utilSuggestNames(preset, suggestions) {
38119     preset = preset.id.split('/', 2);
38120     var k = preset[0],
38121         v = preset[1];
38122
38123     return function(value, callback) {
38124         var result = [];
38125         if (value && value.length > 2) {
38126             if (suggestions[k] && suggestions[k][v]) {
38127                 for (var sugg in suggestions[k][v]) {
38128                     var dist = utilEditDistance(value, sugg.substring(0, value.length));
38129                     if (dist < 3) {
38130                         result.push({
38131                             title: sugg,
38132                             value: sugg,
38133                             dist: dist
38134                         });
38135                     }
38136                 }
38137             }
38138             result.sort(function(a, b) {
38139                 return a.dist - b.dist;
38140             });
38141         }
38142         result = result.slice(0,3);
38143         callback(result);
38144     };
38145 }
38146
38147 function utilTriggerEvent(target, type) {
38148     target.each(function() {
38149         var evt = document.createEvent('HTMLEvents');
38150         evt.initEvent(type, true, true);
38151         this.dispatchEvent(evt);
38152     });
38153 }
38154
38155 function validationDeprecatedTag() {
38156
38157     var validation = function(changes) {
38158         var warnings = [];
38159         for (var i = 0; i < changes.created.length; i++) {
38160             var change = changes.created[i],
38161                 deprecatedTags = change.deprecatedTags();
38162
38163             if (!lodash.isEmpty(deprecatedTags)) {
38164                 var tags = utilTagText({ tags: deprecatedTags });
38165                 warnings.push({
38166                     id: 'deprecated_tags',
38167                     message: t('validations.deprecated_tags', { tags: tags }),
38168                     entity: change
38169                 });
38170             }
38171         }
38172
38173         return warnings;
38174     };
38175
38176
38177     return validation;
38178 }
38179
38180 function validationDisconnectedHighway() {
38181
38182
38183     function isDisconnectedHighway(entity, graph) {
38184         if (!entity.tags.highway) return false;
38185         if (entity.geometry(graph) !== 'line') return false;
38186
38187         return graph.childNodes(entity)
38188             .every(function(vertex) {
38189                 return graph.parentWays(vertex)
38190                     .filter(function(parent) {
38191                         return parent.tags.highway && parent !== entity;
38192                     })
38193                     .length === 0;
38194             });
38195     }
38196
38197
38198     var validation = function(changes, graph) {
38199         var warnings = [];
38200         for (var i = 0; i < changes.created.length; i++) {
38201             var entity = changes.created[i];
38202
38203             if (isDisconnectedHighway(entity, graph)) {
38204                 warnings.push({
38205                     id: 'missing_tag',
38206                     message: t('validations.disconnected_highway'),
38207                     tooltip: t('validations.disconnected_highway_tooltip'),
38208                     entity: entity
38209                 });
38210             }
38211         }
38212
38213         return warnings;
38214     };
38215
38216
38217     return validation;
38218 }
38219
38220 function validationManyDeletions() {
38221     var threshold = 100;
38222
38223     var validation = function(changes) {
38224         var warnings = [];
38225         if (changes.deleted.length > threshold) {
38226             warnings.push({
38227                 id: 'many_deletions',
38228                 message: t('validations.many_deletions', { n: changes.deleted.length })
38229             });
38230         }
38231
38232         return warnings;
38233     };
38234
38235
38236     return validation;
38237 }
38238
38239 function validationMissingTag() {
38240
38241     // Slightly stricter check than Entity#isUsed (#3091)
38242     function hasTags(entity, graph) {
38243         return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
38244             graph.parentRelations(entity).length > 0;
38245     }
38246
38247     var validation = function(changes, graph) {
38248         var types = ['point', 'line', 'area', 'relation'],
38249             warnings = [];
38250
38251         for (var i = 0; i < changes.created.length; i++) {
38252             var change = changes.created[i],
38253                 geometry = change.geometry(graph);
38254
38255             if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
38256                 warnings.push({
38257                     id: 'missing_tag',
38258                     message: t('validations.untagged_' + geometry),
38259                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
38260                     entity: change
38261                 });
38262             }
38263         }
38264
38265         return warnings;
38266     };
38267
38268
38269     return validation;
38270 }
38271
38272 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
38273 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
38274 function validationTagSuggestsArea() {
38275
38276     function tagSuggestsArea(tags) {
38277         if (lodash.isEmpty(tags)) return false;
38278
38279         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
38280         for (var i = 0; i < presence.length; i++) {
38281             if (tags[presence[i]] !== undefined) {
38282                 return presence[i] + '=' + tags[presence[i]];
38283             }
38284         }
38285
38286         if (tags.building && tags.building === 'yes') return 'building=yes';
38287     }
38288
38289
38290     var validation = function(changes, graph) {
38291         var warnings = [];
38292         for (var i = 0; i < changes.created.length; i++) {
38293             var change = changes.created[i],
38294                 geometry = change.geometry(graph),
38295                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
38296
38297             if (suggestion) {
38298                 warnings.push({
38299                     id: 'tag_suggests_area',
38300                     message: t('validations.tag_suggests_area', { tag: suggestion }),
38301                     entity: change
38302                 });
38303             }
38304         }
38305
38306         return warnings;
38307     };
38308
38309
38310     return validation;
38311 }
38312
38313
38314
38315 var Validations = Object.freeze({
38316         validationDeprecatedTag: validationDeprecatedTag,
38317         validationDisconnectedHighway: validationDisconnectedHighway,
38318         validationManyDeletions: validationManyDeletions,
38319         validationMissingTag: validationMissingTag,
38320         validationTagSuggestsArea: validationTagSuggestsArea
38321 });
38322
38323 /*
38324     iD.Difference represents the difference between two graphs.
38325     It knows how to calculate the set of entities that were
38326     created, modified, or deleted, and also contains the logic
38327     for recursively extending a difference to the complete set
38328     of entities that will require a redraw, taking into account
38329     child and parent relationships.
38330  */
38331 function coreDifference(base, head) {
38332     var changes = {},
38333         difference = {},
38334         length = 0;
38335
38336
38337     function changed(h, b) {
38338         return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
38339     }
38340
38341
38342     lodash.each(head.entities, function(h, id) {
38343         var b = base.entities[id];
38344         if (changed(h, b)) {
38345             changes[id] = {base: b, head: h};
38346             length++;
38347         }
38348     });
38349
38350
38351     lodash.each(base.entities, function(b, id) {
38352         var h = head.entities[id];
38353         if (!changes[id] && changed(h, b)) {
38354             changes[id] = {base: b, head: h};
38355             length++;
38356         }
38357     });
38358
38359
38360     function addParents(parents, result) {
38361         for (var i = 0; i < parents.length; i++) {
38362             var parent = parents[i];
38363
38364             if (parent.id in result)
38365                 continue;
38366
38367             result[parent.id] = parent;
38368             addParents(head.parentRelations(parent), result);
38369         }
38370     }
38371
38372
38373     difference.length = function() {
38374         return length;
38375     };
38376
38377
38378     difference.changes = function() {
38379         return changes;
38380     };
38381
38382
38383     difference.extantIDs = function() {
38384         var result = [];
38385         lodash.each(changes, function(change, id) {
38386             if (change.head) result.push(id);
38387         });
38388         return result;
38389     };
38390
38391
38392     difference.modified = function() {
38393         var result = [];
38394         lodash.each(changes, function(change) {
38395             if (change.base && change.head) result.push(change.head);
38396         });
38397         return result;
38398     };
38399
38400
38401     difference.created = function() {
38402         var result = [];
38403         lodash.each(changes, function(change) {
38404             if (!change.base && change.head) result.push(change.head);
38405         });
38406         return result;
38407     };
38408
38409
38410     difference.deleted = function() {
38411         var result = [];
38412         lodash.each(changes, function(change) {
38413             if (change.base && !change.head) result.push(change.base);
38414         });
38415         return result;
38416     };
38417
38418
38419     difference.summary = function() {
38420         var relevant = {};
38421
38422         function addEntity(entity, graph, changeType) {
38423             relevant[entity.id] = {
38424                 entity: entity,
38425                 graph: graph,
38426                 changeType: changeType
38427             };
38428         }
38429
38430         function addParents(entity) {
38431             var parents = head.parentWays(entity);
38432             for (var j = parents.length - 1; j >= 0; j--) {
38433                 var parent = parents[j];
38434                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
38435             }
38436         }
38437
38438         lodash.each(changes, function(change) {
38439             if (change.head && change.head.geometry(head) !== 'vertex') {
38440                 addEntity(change.head, head, change.base ? 'modified' : 'created');
38441
38442             } else if (change.base && change.base.geometry(base) !== 'vertex') {
38443                 addEntity(change.base, base, 'deleted');
38444
38445             } else if (change.base && change.head) { // modified vertex
38446                 var moved    = !lodash.isEqual(change.base.loc,  change.head.loc),
38447                     retagged = !lodash.isEqual(change.base.tags, change.head.tags);
38448
38449                 if (moved) {
38450                     addParents(change.head);
38451                 }
38452
38453                 if (retagged || (moved && change.head.hasInterestingTags())) {
38454                     addEntity(change.head, head, 'modified');
38455                 }
38456
38457             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
38458                 addEntity(change.head, head, 'created');
38459
38460             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
38461                 addEntity(change.base, base, 'deleted');
38462             }
38463         });
38464
38465         return values(relevant);
38466     };
38467
38468
38469     difference.complete = function(extent$$1) {
38470         var result = {}, id, change;
38471
38472         for (id in changes) {
38473             change = changes[id];
38474
38475             var h = change.head,
38476                 b = change.base,
38477                 entity = h || b;
38478
38479             if (extent$$1 &&
38480                 (!h || !h.intersects(extent$$1, head)) &&
38481                 (!b || !b.intersects(extent$$1, base)))
38482                 continue;
38483
38484             result[id] = h;
38485
38486             if (entity.type === 'way') {
38487                 var nh = h ? h.nodes : [],
38488                     nb = b ? b.nodes : [],
38489                     diff, i;
38490
38491                 diff = lodash.difference(nh, nb);
38492                 for (i = 0; i < diff.length; i++) {
38493                     result[diff[i]] = head.hasEntity(diff[i]);
38494                 }
38495
38496                 diff = lodash.difference(nb, nh);
38497                 for (i = 0; i < diff.length; i++) {
38498                     result[diff[i]] = head.hasEntity(diff[i]);
38499                 }
38500             }
38501
38502             addParents(head.parentWays(entity), result);
38503             addParents(head.parentRelations(entity), result);
38504         }
38505
38506         return result;
38507     };
38508
38509
38510     return difference;
38511 }
38512
38513 function coreGraph$$1(other, mutable) {
38514     if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38515
38516     if (other instanceof coreGraph$$1) {
38517         var base = other.base();
38518         this.entities = lodash.assign(Object.create(base.entities), other.entities);
38519         this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38520         this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38521
38522     } else {
38523         this.entities = Object.create({});
38524         this._parentWays = Object.create({});
38525         this._parentRels = Object.create({});
38526         this.rebase(other || [], [this]);
38527     }
38528
38529     this.transients = {};
38530     this._childNodes = {};
38531     this.frozen = !mutable;
38532 }
38533
38534
38535 coreGraph$$1.prototype = {
38536
38537     hasEntity: function(id) {
38538         return this.entities[id];
38539     },
38540
38541
38542     entity: function(id) {
38543         var entity = this.entities[id];
38544         if (!entity) {
38545             throw new Error('entity ' + id + ' not found');
38546         }
38547         return entity;
38548     },
38549
38550
38551     transient: function(entity, key, fn) {
38552         var id = entity.id,
38553             transients = this.transients[id] ||
38554             (this.transients[id] = {});
38555
38556         if (transients[key] !== undefined) {
38557             return transients[key];
38558         }
38559
38560         transients[key] = fn.call(entity);
38561
38562         return transients[key];
38563     },
38564
38565
38566     parentWays: function(entity) {
38567         var parents = this._parentWays[entity.id],
38568             result = [];
38569
38570         if (parents) {
38571             for (var i = 0; i < parents.length; i++) {
38572                 result.push(this.entity(parents[i]));
38573             }
38574         }
38575         return result;
38576     },
38577
38578
38579     isPoi: function(entity) {
38580         var parentWays = this._parentWays[entity.id];
38581         return !parentWays || parentWays.length === 0;
38582     },
38583
38584
38585     isShared: function(entity) {
38586         var parentWays = this._parentWays[entity.id];
38587         return parentWays && parentWays.length > 1;
38588     },
38589
38590
38591     parentRelations: function(entity) {
38592         var parents = this._parentRels[entity.id],
38593             result = [];
38594
38595         if (parents) {
38596             for (var i = 0; i < parents.length; i++) {
38597                 result.push(this.entity(parents[i]));
38598             }
38599         }
38600         return result;
38601     },
38602
38603
38604     childNodes: function(entity) {
38605         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38606         if (!entity.nodes) return [];
38607
38608         var nodes = [];
38609         for (var i = 0; i < entity.nodes.length; i++) {
38610             nodes[i] = this.entity(entity.nodes[i]);
38611         }
38612
38613         if (debug) Object.freeze(nodes);
38614
38615         this._childNodes[entity.id] = nodes;
38616         return this._childNodes[entity.id];
38617     },
38618
38619
38620     base: function() {
38621         return {
38622             'entities': utilGetPrototypeOf(this.entities),
38623             'parentWays': utilGetPrototypeOf(this._parentWays),
38624             'parentRels': utilGetPrototypeOf(this._parentRels)
38625         };
38626     },
38627
38628
38629     // Unlike other graph methods, rebase mutates in place. This is because it
38630     // is used only during the history operation that merges newly downloaded
38631     // data into each state. To external consumers, it should appear as if the
38632     // graph always contained the newly downloaded data.
38633     rebase: function(entities, stack, force) {
38634         var base = this.base(),
38635             i, j, k, id;
38636
38637         for (i = 0; i < entities.length; i++) {
38638             var entity = entities[i];
38639
38640             if (!entity.visible || (!force && base.entities[entity.id]))
38641                 continue;
38642
38643             // Merging data into the base graph
38644             base.entities[entity.id] = entity;
38645             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38646
38647             // Restore provisionally-deleted nodes that are discovered to have an extant parent
38648             if (entity.type === 'way') {
38649                 for (j = 0; j < entity.nodes.length; j++) {
38650                     id = entity.nodes[j];
38651                     for (k = 1; k < stack.length; k++) {
38652                         var ents = stack[k].entities;
38653                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38654                             delete ents[id];
38655                         }
38656                     }
38657                 }
38658             }
38659         }
38660
38661         for (i = 0; i < stack.length; i++) {
38662             stack[i]._updateRebased();
38663         }
38664     },
38665
38666
38667     _updateRebased: function() {
38668         var base = this.base(),
38669             i, k, child, id, keys;
38670
38671         keys = Object.keys(this._parentWays);
38672         for (i = 0; i < keys.length; i++) {
38673             child = keys[i];
38674             if (base.parentWays[child]) {
38675                 for (k = 0; k < base.parentWays[child].length; k++) {
38676                     id = base.parentWays[child][k];
38677                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38678                         this._parentWays[child].push(id);
38679                     }
38680                 }
38681             }
38682         }
38683
38684         keys = Object.keys(this._parentRels);
38685         for (i = 0; i < keys.length; i++) {
38686             child = keys[i];
38687             if (base.parentRels[child]) {
38688                 for (k = 0; k < base.parentRels[child].length; k++) {
38689                     id = base.parentRels[child][k];
38690                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38691                         this._parentRels[child].push(id);
38692                     }
38693                 }
38694             }
38695         }
38696
38697         this.transients = {};
38698
38699         // this._childNodes is not updated, under the assumption that
38700         // ways are always downloaded with their child nodes.
38701     },
38702
38703
38704     // Updates calculated properties (parentWays, parentRels) for the specified change
38705     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38706
38707         parentWays = parentWays || this._parentWays;
38708         parentRels = parentRels || this._parentRels;
38709
38710         var type = entity && entity.type || oldentity && oldentity.type,
38711             removed, added, ways, rels, i;
38712
38713
38714         if (type === 'way') {
38715
38716             // Update parentWays
38717             if (oldentity && entity) {
38718                 removed = lodash.difference(oldentity.nodes, entity.nodes);
38719                 added = lodash.difference(entity.nodes, oldentity.nodes);
38720             } else if (oldentity) {
38721                 removed = oldentity.nodes;
38722                 added = [];
38723             } else if (entity) {
38724                 removed = [];
38725                 added = entity.nodes;
38726             }
38727             for (i = 0; i < removed.length; i++) {
38728                 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38729             }
38730             for (i = 0; i < added.length; i++) {
38731                 ways = lodash.without(parentWays[added[i]], entity.id);
38732                 ways.push(entity.id);
38733                 parentWays[added[i]] = ways;
38734             }
38735
38736         } else if (type === 'relation') {
38737
38738             // Update parentRels
38739             if (oldentity && entity) {
38740                 removed = lodash.difference(oldentity.members, entity.members);
38741                 added = lodash.difference(entity.members, oldentity);
38742             } else if (oldentity) {
38743                 removed = oldentity.members;
38744                 added = [];
38745             } else if (entity) {
38746                 removed = [];
38747                 added = entity.members;
38748             }
38749             for (i = 0; i < removed.length; i++) {
38750                 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38751             }
38752             for (i = 0; i < added.length; i++) {
38753                 rels = lodash.without(parentRels[added[i].id], entity.id);
38754                 rels.push(entity.id);
38755                 parentRels[added[i].id] = rels;
38756             }
38757         }
38758     },
38759
38760
38761     replace: function(entity) {
38762         if (this.entities[entity.id] === entity)
38763             return this;
38764
38765         return this.update(function() {
38766             this._updateCalculated(this.entities[entity.id], entity);
38767             this.entities[entity.id] = entity;
38768         });
38769     },
38770
38771
38772     remove: function(entity) {
38773         return this.update(function() {
38774             this._updateCalculated(entity, undefined);
38775             this.entities[entity.id] = undefined;
38776         });
38777     },
38778
38779
38780     revert: function(id) {
38781         var baseEntity = this.base().entities[id],
38782             headEntity = this.entities[id];
38783
38784         if (headEntity === baseEntity)
38785             return this;
38786
38787         return this.update(function() {
38788             this._updateCalculated(headEntity, baseEntity);
38789             delete this.entities[id];
38790         });
38791     },
38792
38793
38794     update: function() {
38795         var graph = this.frozen ? coreGraph$$1(this, true) : this;
38796
38797         for (var i = 0; i < arguments.length; i++) {
38798             arguments[i].call(graph, graph);
38799         }
38800
38801         if (this.frozen) graph.frozen = true;
38802
38803         return graph;
38804     },
38805
38806
38807     // Obliterates any existing entities
38808     load: function(entities) {
38809         var base = this.base();
38810         this.entities = Object.create(base.entities);
38811
38812         for (var i in entities) {
38813             this.entities[i] = entities[i];
38814             this._updateCalculated(base.entities[i], this.entities[i]);
38815         }
38816
38817         return this;
38818     }
38819 };
38820
38821 var index$10 = partialSort;
38822
38823 // Floyd-Rivest selection algorithm:
38824 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38825 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38826
38827 function partialSort(arr, k, left, right, compare) {
38828     left = left || 0;
38829     right = right || (arr.length - 1);
38830     compare = compare || defaultCompare;
38831
38832     while (right > left) {
38833         if (right - left > 600) {
38834             var n = right - left + 1;
38835             var m = k - left + 1;
38836             var z = Math.log(n);
38837             var s = 0.5 * Math.exp(2 * z / 3);
38838             var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38839             var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38840             var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38841             partialSort(arr, k, newLeft, newRight, compare);
38842         }
38843
38844         var t = arr[k];
38845         var i = left;
38846         var j = right;
38847
38848         swap(arr, left, k);
38849         if (compare(arr[right], t) > 0) swap(arr, left, right);
38850
38851         while (i < j) {
38852             swap(arr, i, j);
38853             i++;
38854             j--;
38855             while (compare(arr[i], t) < 0) i++;
38856             while (compare(arr[j], t) > 0) j--;
38857         }
38858
38859         if (compare(arr[left], t) === 0) swap(arr, left, j);
38860         else {
38861             j++;
38862             swap(arr, j, right);
38863         }
38864
38865         if (j <= k) left = j + 1;
38866         if (k <= j) right = j - 1;
38867     }
38868 }
38869
38870 function swap(arr, i, j) {
38871     var tmp = arr[i];
38872     arr[i] = arr[j];
38873     arr[j] = tmp;
38874 }
38875
38876 function defaultCompare(a, b) {
38877     return a < b ? -1 : a > b ? 1 : 0;
38878 }
38879
38880 var index$9 = rbush;
38881
38882 var quickselect = index$10;
38883
38884 function rbush(maxEntries, format) {
38885     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38886
38887     // max entries in a node is 9 by default; min node fill is 40% for best performance
38888     this._maxEntries = Math.max(4, maxEntries || 9);
38889     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38890
38891     if (format) {
38892         this._initFormat(format);
38893     }
38894
38895     this.clear();
38896 }
38897
38898 rbush.prototype = {
38899
38900     all: function () {
38901         return this._all(this.data, []);
38902     },
38903
38904     search: function (bbox) {
38905
38906         var node = this.data,
38907             result = [],
38908             toBBox = this.toBBox;
38909
38910         if (!intersects$1(bbox, node)) return result;
38911
38912         var nodesToSearch = [],
38913             i, len, child, childBBox;
38914
38915         while (node) {
38916             for (i = 0, len = node.children.length; i < len; i++) {
38917
38918                 child = node.children[i];
38919                 childBBox = node.leaf ? toBBox(child) : child;
38920
38921                 if (intersects$1(bbox, childBBox)) {
38922                     if (node.leaf) result.push(child);
38923                     else if (contains$1(bbox, childBBox)) this._all(child, result);
38924                     else nodesToSearch.push(child);
38925                 }
38926             }
38927             node = nodesToSearch.pop();
38928         }
38929
38930         return result;
38931     },
38932
38933     collides: function (bbox) {
38934
38935         var node = this.data,
38936             toBBox = this.toBBox;
38937
38938         if (!intersects$1(bbox, node)) return false;
38939
38940         var nodesToSearch = [],
38941             i, len, child, childBBox;
38942
38943         while (node) {
38944             for (i = 0, len = node.children.length; i < len; i++) {
38945
38946                 child = node.children[i];
38947                 childBBox = node.leaf ? toBBox(child) : child;
38948
38949                 if (intersects$1(bbox, childBBox)) {
38950                     if (node.leaf || contains$1(bbox, childBBox)) return true;
38951                     nodesToSearch.push(child);
38952                 }
38953             }
38954             node = nodesToSearch.pop();
38955         }
38956
38957         return false;
38958     },
38959
38960     load: function (data) {
38961         if (!(data && data.length)) return this;
38962
38963         if (data.length < this._minEntries) {
38964             for (var i = 0, len = data.length; i < len; i++) {
38965                 this.insert(data[i]);
38966             }
38967             return this;
38968         }
38969
38970         // recursively build the tree with the given data from stratch using OMT algorithm
38971         var node = this._build(data.slice(), 0, data.length - 1, 0);
38972
38973         if (!this.data.children.length) {
38974             // save as is if tree is empty
38975             this.data = node;
38976
38977         } else if (this.data.height === node.height) {
38978             // split root if trees have the same height
38979             this._splitRoot(this.data, node);
38980
38981         } else {
38982             if (this.data.height < node.height) {
38983                 // swap trees if inserted one is bigger
38984                 var tmpNode = this.data;
38985                 this.data = node;
38986                 node = tmpNode;
38987             }
38988
38989             // insert the small tree into the large tree at appropriate level
38990             this._insert(node, this.data.height - node.height - 1, true);
38991         }
38992
38993         return this;
38994     },
38995
38996     insert: function (item) {
38997         if (item) this._insert(item, this.data.height - 1);
38998         return this;
38999     },
39000
39001     clear: function () {
39002         this.data = createNode([]);
39003         return this;
39004     },
39005
39006     remove: function (item, equalsFn) {
39007         if (!item) return this;
39008
39009         var node = this.data,
39010             bbox = this.toBBox(item),
39011             path = [],
39012             indexes = [],
39013             i, parent, index, goingUp;
39014
39015         // depth-first iterative tree traversal
39016         while (node || path.length) {
39017
39018             if (!node) { // go up
39019                 node = path.pop();
39020                 parent = path[path.length - 1];
39021                 i = indexes.pop();
39022                 goingUp = true;
39023             }
39024
39025             if (node.leaf) { // check current node
39026                 index = findItem(item, node.children, equalsFn);
39027
39028                 if (index !== -1) {
39029                     // item found, remove the item and condense tree upwards
39030                     node.children.splice(index, 1);
39031                     path.push(node);
39032                     this._condense(path);
39033                     return this;
39034                 }
39035             }
39036
39037             if (!goingUp && !node.leaf && contains$1(node, bbox)) { // go down
39038                 path.push(node);
39039                 indexes.push(i);
39040                 i = 0;
39041                 parent = node;
39042                 node = node.children[0];
39043
39044             } else if (parent) { // go right
39045                 i++;
39046                 node = parent.children[i];
39047                 goingUp = false;
39048
39049             } else node = null; // nothing found
39050         }
39051
39052         return this;
39053     },
39054
39055     toBBox: function (item) { return item; },
39056
39057     compareMinX: compareNodeMinX,
39058     compareMinY: compareNodeMinY,
39059
39060     toJSON: function () { return this.data; },
39061
39062     fromJSON: function (data) {
39063         this.data = data;
39064         return this;
39065     },
39066
39067     _all: function (node, result) {
39068         var nodesToSearch = [];
39069         while (node) {
39070             if (node.leaf) result.push.apply(result, node.children);
39071             else nodesToSearch.push.apply(nodesToSearch, node.children);
39072
39073             node = nodesToSearch.pop();
39074         }
39075         return result;
39076     },
39077
39078     _build: function (items, left, right, height) {
39079
39080         var N = right - left + 1,
39081             M = this._maxEntries,
39082             node;
39083
39084         if (N <= M) {
39085             // reached leaf level; return leaf
39086             node = createNode(items.slice(left, right + 1));
39087             calcBBox(node, this.toBBox);
39088             return node;
39089         }
39090
39091         if (!height) {
39092             // target height of the bulk-loaded tree
39093             height = Math.ceil(Math.log(N) / Math.log(M));
39094
39095             // target number of root entries to maximize storage utilization
39096             M = Math.ceil(N / Math.pow(M, height - 1));
39097         }
39098
39099         node = createNode([]);
39100         node.leaf = false;
39101         node.height = height;
39102
39103         // split the items into M mostly square tiles
39104
39105         var N2 = Math.ceil(N / M),
39106             N1 = N2 * Math.ceil(Math.sqrt(M)),
39107             i, j, right2, right3;
39108
39109         multiSelect(items, left, right, N1, this.compareMinX);
39110
39111         for (i = left; i <= right; i += N1) {
39112
39113             right2 = Math.min(i + N1 - 1, right);
39114
39115             multiSelect(items, i, right2, N2, this.compareMinY);
39116
39117             for (j = i; j <= right2; j += N2) {
39118
39119                 right3 = Math.min(j + N2 - 1, right2);
39120
39121                 // pack each entry recursively
39122                 node.children.push(this._build(items, j, right3, height - 1));
39123             }
39124         }
39125
39126         calcBBox(node, this.toBBox);
39127
39128         return node;
39129     },
39130
39131     _chooseSubtree: function (bbox, node, level, path) {
39132
39133         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
39134
39135         while (true) {
39136             path.push(node);
39137
39138             if (node.leaf || path.length - 1 === level) break;
39139
39140             minArea = minEnlargement = Infinity;
39141
39142             for (i = 0, len = node.children.length; i < len; i++) {
39143                 child = node.children[i];
39144                 area = bboxArea(child);
39145                 enlargement = enlargedArea(bbox, child) - area;
39146
39147                 // choose entry with the least area enlargement
39148                 if (enlargement < minEnlargement) {
39149                     minEnlargement = enlargement;
39150                     minArea = area < minArea ? area : minArea;
39151                     targetNode = child;
39152
39153                 } else if (enlargement === minEnlargement) {
39154                     // otherwise choose one with the smallest area
39155                     if (area < minArea) {
39156                         minArea = area;
39157                         targetNode = child;
39158                     }
39159                 }
39160             }
39161
39162             node = targetNode || node.children[0];
39163         }
39164
39165         return node;
39166     },
39167
39168     _insert: function (item, level, isNode) {
39169
39170         var toBBox = this.toBBox,
39171             bbox = isNode ? item : toBBox(item),
39172             insertPath = [];
39173
39174         // find the best node for accommodating the item, saving all nodes along the path too
39175         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
39176
39177         // put the item into the node
39178         node.children.push(item);
39179         extend$1(node, bbox);
39180
39181         // split on node overflow; propagate upwards if necessary
39182         while (level >= 0) {
39183             if (insertPath[level].children.length > this._maxEntries) {
39184                 this._split(insertPath, level);
39185                 level--;
39186             } else break;
39187         }
39188
39189         // adjust bboxes along the insertion path
39190         this._adjustParentBBoxes(bbox, insertPath, level);
39191     },
39192
39193     // split overflowed node into two
39194     _split: function (insertPath, level) {
39195
39196         var node = insertPath[level],
39197             M = node.children.length,
39198             m = this._minEntries;
39199
39200         this._chooseSplitAxis(node, m, M);
39201
39202         var splitIndex = this._chooseSplitIndex(node, m, M);
39203
39204         var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
39205         newNode.height = node.height;
39206         newNode.leaf = node.leaf;
39207
39208         calcBBox(node, this.toBBox);
39209         calcBBox(newNode, this.toBBox);
39210
39211         if (level) insertPath[level - 1].children.push(newNode);
39212         else this._splitRoot(node, newNode);
39213     },
39214
39215     _splitRoot: function (node, newNode) {
39216         // split root node
39217         this.data = createNode([node, newNode]);
39218         this.data.height = node.height + 1;
39219         this.data.leaf = false;
39220         calcBBox(this.data, this.toBBox);
39221     },
39222
39223     _chooseSplitIndex: function (node, m, M) {
39224
39225         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
39226
39227         minOverlap = minArea = Infinity;
39228
39229         for (i = m; i <= M - m; i++) {
39230             bbox1 = distBBox(node, 0, i, this.toBBox);
39231             bbox2 = distBBox(node, i, M, this.toBBox);
39232
39233             overlap = intersectionArea(bbox1, bbox2);
39234             area = bboxArea(bbox1) + bboxArea(bbox2);
39235
39236             // choose distribution with minimum overlap
39237             if (overlap < minOverlap) {
39238                 minOverlap = overlap;
39239                 index = i;
39240
39241                 minArea = area < minArea ? area : minArea;
39242
39243             } else if (overlap === minOverlap) {
39244                 // otherwise choose distribution with minimum area
39245                 if (area < minArea) {
39246                     minArea = area;
39247                     index = i;
39248                 }
39249             }
39250         }
39251
39252         return index;
39253     },
39254
39255     // sorts node children by the best axis for split
39256     _chooseSplitAxis: function (node, m, M) {
39257
39258         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
39259             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
39260             xMargin = this._allDistMargin(node, m, M, compareMinX),
39261             yMargin = this._allDistMargin(node, m, M, compareMinY);
39262
39263         // if total distributions margin value is minimal for x, sort by minX,
39264         // otherwise it's already sorted by minY
39265         if (xMargin < yMargin) node.children.sort(compareMinX);
39266     },
39267
39268     // total margin of all possible split distributions where each node is at least m full
39269     _allDistMargin: function (node, m, M, compare) {
39270
39271         node.children.sort(compare);
39272
39273         var toBBox = this.toBBox,
39274             leftBBox = distBBox(node, 0, m, toBBox),
39275             rightBBox = distBBox(node, M - m, M, toBBox),
39276             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
39277             i, child;
39278
39279         for (i = m; i < M - m; i++) {
39280             child = node.children[i];
39281             extend$1(leftBBox, node.leaf ? toBBox(child) : child);
39282             margin += bboxMargin(leftBBox);
39283         }
39284
39285         for (i = M - m - 1; i >= m; i--) {
39286             child = node.children[i];
39287             extend$1(rightBBox, node.leaf ? toBBox(child) : child);
39288             margin += bboxMargin(rightBBox);
39289         }
39290
39291         return margin;
39292     },
39293
39294     _adjustParentBBoxes: function (bbox, path, level) {
39295         // adjust bboxes along the given tree path
39296         for (var i = level; i >= 0; i--) {
39297             extend$1(path[i], bbox);
39298         }
39299     },
39300
39301     _condense: function (path) {
39302         // go through the path, removing empty nodes and updating bboxes
39303         for (var i = path.length - 1, siblings; i >= 0; i--) {
39304             if (path[i].children.length === 0) {
39305                 if (i > 0) {
39306                     siblings = path[i - 1].children;
39307                     siblings.splice(siblings.indexOf(path[i]), 1);
39308
39309                 } else this.clear();
39310
39311             } else calcBBox(path[i], this.toBBox);
39312         }
39313     },
39314
39315     _initFormat: function (format) {
39316         // data format (minX, minY, maxX, maxY accessors)
39317
39318         // uses eval-type function compilation instead of just accepting a toBBox function
39319         // because the algorithms are very sensitive to sorting functions performance,
39320         // so they should be dead simple and without inner calls
39321
39322         var compareArr = ['return a', ' - b', ';'];
39323
39324         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
39325         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
39326
39327         this.toBBox = new Function('a',
39328             'return {minX: a' + format[0] +
39329             ', minY: a' + format[1] +
39330             ', maxX: a' + format[2] +
39331             ', maxY: a' + format[3] + '};');
39332     }
39333 };
39334
39335 function findItem(item, items, equalsFn) {
39336     if (!equalsFn) return items.indexOf(item);
39337
39338     for (var i = 0; i < items.length; i++) {
39339         if (equalsFn(item, items[i])) return i;
39340     }
39341     return -1;
39342 }
39343
39344 // calculate node's bbox from bboxes of its children
39345 function calcBBox(node, toBBox) {
39346     distBBox(node, 0, node.children.length, toBBox, node);
39347 }
39348
39349 // min bounding rectangle of node children from k to p-1
39350 function distBBox(node, k, p, toBBox, destNode) {
39351     if (!destNode) destNode = createNode(null);
39352     destNode.minX = Infinity;
39353     destNode.minY = Infinity;
39354     destNode.maxX = -Infinity;
39355     destNode.maxY = -Infinity;
39356
39357     for (var i = k, child; i < p; i++) {
39358         child = node.children[i];
39359         extend$1(destNode, node.leaf ? toBBox(child) : child);
39360     }
39361
39362     return destNode;
39363 }
39364
39365 function extend$1(a, b) {
39366     a.minX = Math.min(a.minX, b.minX);
39367     a.minY = Math.min(a.minY, b.minY);
39368     a.maxX = Math.max(a.maxX, b.maxX);
39369     a.maxY = Math.max(a.maxY, b.maxY);
39370     return a;
39371 }
39372
39373 function compareNodeMinX(a, b) { return a.minX - b.minX; }
39374 function compareNodeMinY(a, b) { return a.minY - b.minY; }
39375
39376 function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
39377 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
39378
39379 function enlargedArea(a, b) {
39380     return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
39381            (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
39382 }
39383
39384 function intersectionArea(a, b) {
39385     var minX = Math.max(a.minX, b.minX),
39386         minY = Math.max(a.minY, b.minY),
39387         maxX = Math.min(a.maxX, b.maxX),
39388         maxY = Math.min(a.maxY, b.maxY);
39389
39390     return Math.max(0, maxX - minX) *
39391            Math.max(0, maxY - minY);
39392 }
39393
39394 function contains$1(a, b) {
39395     return a.minX <= b.minX &&
39396            a.minY <= b.minY &&
39397            b.maxX <= a.maxX &&
39398            b.maxY <= a.maxY;
39399 }
39400
39401 function intersects$1(a, b) {
39402     return b.minX <= a.maxX &&
39403            b.minY <= a.maxY &&
39404            b.maxX >= a.minX &&
39405            b.maxY >= a.minY;
39406 }
39407
39408 function createNode(children) {
39409     return {
39410         children: children,
39411         height: 1,
39412         leaf: true,
39413         minX: Infinity,
39414         minY: Infinity,
39415         maxX: -Infinity,
39416         maxY: -Infinity
39417     };
39418 }
39419
39420 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
39421 // combines selection algorithm with binary divide & conquer approach
39422
39423 function multiSelect(arr, left, right, n, compare) {
39424     var stack = [left, right],
39425         mid;
39426
39427     while (stack.length) {
39428         right = stack.pop();
39429         left = stack.pop();
39430
39431         if (right - left <= n) continue;
39432
39433         mid = left + Math.ceil((right - left) / n / 2) * n;
39434         quickselect(arr, mid, left, right, compare);
39435
39436         stack.push(left, mid, mid, right);
39437     }
39438 }
39439
39440 function coreTree(head) {
39441     var rtree = index$9(),
39442         bboxes = {},
39443         tree = {};
39444
39445
39446     function entityBBox(entity) {
39447         var bbox = entity.extent(head).bbox();
39448         bbox.id = entity.id;
39449         bboxes[entity.id] = bbox;
39450         return bbox;
39451     }
39452
39453
39454     function updateParents(entity, insertions, memo) {
39455         head.parentWays(entity).forEach(function(way) {
39456             if (bboxes[way.id]) {
39457                 rtree.remove(bboxes[way.id]);
39458                 insertions[way.id] = way;
39459             }
39460             updateParents(way, insertions, memo);
39461         });
39462
39463         head.parentRelations(entity).forEach(function(relation) {
39464             if (memo[entity.id]) return;
39465             memo[entity.id] = true;
39466             if (bboxes[relation.id]) {
39467                 rtree.remove(bboxes[relation.id]);
39468                 insertions[relation.id] = relation;
39469             }
39470             updateParents(relation, insertions, memo);
39471         });
39472     }
39473
39474
39475     tree.rebase = function(entities, force) {
39476         var insertions = {};
39477
39478         for (var i = 0; i < entities.length; i++) {
39479             var entity = entities[i];
39480
39481             if (!entity.visible)
39482                 continue;
39483
39484             if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
39485                 if (!force) {
39486                     continue;
39487                 } else if (bboxes[entity.id]) {
39488                     rtree.remove(bboxes[entity.id]);
39489                 }
39490             }
39491
39492             insertions[entity.id] = entity;
39493             updateParents(entity, insertions, {});
39494         }
39495
39496         rtree.load(lodash.map(insertions, entityBBox));
39497
39498         return tree;
39499     };
39500
39501
39502     tree.intersects = function(extent, graph) {
39503         if (graph !== head) {
39504             var diff = coreDifference(head, graph),
39505                 insertions = {};
39506
39507             head = graph;
39508
39509             diff.deleted().forEach(function(entity) {
39510                 rtree.remove(bboxes[entity.id]);
39511                 delete bboxes[entity.id];
39512             });
39513
39514             diff.modified().forEach(function(entity) {
39515                 rtree.remove(bboxes[entity.id]);
39516                 insertions[entity.id] = entity;
39517                 updateParents(entity, insertions, {});
39518             });
39519
39520             diff.created().forEach(function(entity) {
39521                 insertions[entity.id] = entity;
39522             });
39523
39524             rtree.load(lodash.map(insertions, entityBBox));
39525         }
39526
39527         return rtree.search(extent.bbox()).map(function(bbox) {
39528             return head.entity(bbox.id);
39529         });
39530     };
39531
39532
39533     return tree;
39534 }
39535
39536 /*
39537  * This code is licensed under the MIT license.
39538  *
39539  * Copyright © 2013, iD authors.
39540  *
39541  * Portions copyright © 2011, Keith Cirkel
39542  * See https://github.com/keithamus/jwerty
39543  *
39544  */
39545 function d3keybinding(namespace$$1) {
39546     var bindings = [];
39547
39548     function matches(binding, event$$1) {
39549         for (var p in binding.event) {
39550             if (event$$1[p] !== binding.event[p])
39551                 return false;
39552         }
39553         return true;
39554     }
39555
39556     function testBindings(isCapturing) {
39557         for (var i = 0; i < bindings.length; i++) {
39558             var binding = bindings[i];
39559
39560             if (!!binding.capture === isCapturing && matches(binding, event)) {
39561                 binding.callback();
39562             }
39563         }
39564     }
39565
39566     function capture() {
39567         testBindings(true);
39568     }
39569
39570     function bubble() {
39571         var tagName = select(event.target).node().tagName;
39572         if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39573             return;
39574         }
39575         testBindings(false);
39576     }
39577
39578     function keybinding(selection$$1) {
39579         selection$$1 = selection$$1 || select(document);
39580         selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39581         selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39582         return keybinding;
39583     }
39584
39585     keybinding.off = function(selection$$1) {
39586         bindings = [];
39587         selection$$1 = selection$$1 || select(document);
39588         selection$$1.on('keydown.capture' + namespace$$1, null);
39589         selection$$1.on('keydown.bubble' + namespace$$1, null);
39590         return keybinding;
39591     };
39592
39593     keybinding.on = function(codes, callback, capture) {
39594         var arr = [].concat(codes);
39595         for (var i = 0; i < arr.length; i++) {
39596             var code = arr[i];
39597             var binding = {
39598                 event: {
39599                     keyCode: 0,
39600                     shiftKey: false,
39601                     ctrlKey: false,
39602                     altKey: false,
39603                     metaKey: false
39604                 },
39605                 capture: capture,
39606                 callback: callback
39607             };
39608
39609             code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39610
39611             for (var j = 0; j < code.length; j++) {
39612                 // Normalise matching errors
39613                 if (code[j] === '++') code[i] = '+';
39614
39615                 if (code[j] in d3keybinding.modifierCodes) {
39616                     binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39617                 } else if (code[j] in d3keybinding.keyCodes) {
39618                     binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39619                 }
39620             }
39621
39622             bindings.push(binding);
39623         }
39624
39625         return keybinding;
39626     };
39627
39628     return keybinding;
39629 }
39630
39631
39632 d3keybinding.modifierCodes = {
39633     // Shift key, ⇧
39634     '⇧': 16, shift: 16,
39635     // CTRL key, on Mac: ⌃
39636     '⌃': 17, ctrl: 17,
39637     // ALT key, on Mac: ⌥ (Alt)
39638     '⌥': 18, alt: 18, option: 18,
39639     // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39640     '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39641 };
39642
39643 d3keybinding.modifierProperties = {
39644     16: 'shiftKey',
39645     17: 'ctrlKey',
39646     18: 'altKey',
39647     91: 'metaKey'
39648 };
39649
39650 d3keybinding.keyCodes = {
39651     // Backspace key, on Mac: ⌫ (Backspace)
39652     '⌫': 8, backspace: 8,
39653     // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39654     '⇥': 9, '⇆': 9, tab: 9,
39655     // Return key, ↩
39656     '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39657     // Pause/Break key
39658     'pause': 19, 'pause-break': 19,
39659     // Caps Lock key, ⇪
39660     '⇪': 20, caps: 20, 'caps-lock': 20,
39661     // Escape key, on Mac: ⎋, on Windows: Esc
39662     '⎋': 27, escape: 27, esc: 27,
39663     // Space key
39664     space: 32,
39665     // Page-Up key, or pgup, on Mac: ↖
39666     '↖': 33, pgup: 33, 'page-up': 33,
39667     // Page-Down key, or pgdown, on Mac: ↘
39668     '↘': 34, pgdown: 34, 'page-down': 34,
39669     // END key, on Mac: ⇟
39670     '⇟': 35, end: 35,
39671     // HOME key, on Mac: ⇞
39672     '⇞': 36, home: 36,
39673     // Insert key, or ins
39674     ins: 45, insert: 45,
39675     // Delete key, on Mac: ⌦ (Delete)
39676     '⌦': 46, del: 46, 'delete': 46,
39677     // Left Arrow Key, or ←
39678     '←': 37, left: 37, 'arrow-left': 37,
39679     // Up Arrow Key, or ↑
39680     '↑': 38, up: 38, 'arrow-up': 38,
39681     // Right Arrow Key, or →
39682     '→': 39, right: 39, 'arrow-right': 39,
39683     // Up Arrow Key, or ↓
39684     '↓': 40, down: 40, 'arrow-down': 40,
39685     // odities, printing characters that come out wrong:
39686     // Firefox Equals
39687     'ffequals': 61,
39688     // Num-Multiply, or *
39689     '*': 106, star: 106, asterisk: 106, multiply: 106,
39690     // Num-Plus or +
39691     '+': 107, 'plus': 107,
39692     // Num-Subtract, or -
39693     '-': 109, subtract: 109,
39694     // Firefox Plus
39695     'ffplus': 171,
39696     // Firefox Minus
39697     'ffminus': 173,
39698     // Semicolon
39699     ';': 186, semicolon: 186,
39700     // = or equals
39701     '=': 187, 'equals': 187,
39702     // Comma, or ,
39703     ',': 188, comma: 188,
39704     // Dash / Underscore key
39705     'dash': 189,
39706     // Period, or ., or full-stop
39707     '.': 190, period: 190, 'full-stop': 190,
39708     // Slash, or /, or forward-slash
39709     '/': 191, slash: 191, 'forward-slash': 191,
39710     // Tick, or `, or back-quote
39711     '`': 192, tick: 192, 'back-quote': 192,
39712     // Open bracket, or [
39713     '[': 219, 'open-bracket': 219,
39714     // Back slash, or \
39715     '\\': 220, 'back-slash': 220,
39716     // Close backet, or ]
39717     ']': 221, 'close-bracket': 221,
39718     // Apostrophe, or Quote, or '
39719     '\'': 222, quote: 222, apostrophe: 222
39720 };
39721
39722 // NUMPAD 0-9
39723 var i$1 = 95;
39724 var n = 0;
39725 while (++i$1 < 106) {
39726     d3keybinding.keyCodes['num-' + n] = i$1;
39727     ++n;
39728 }
39729
39730 // 0-9
39731 i$1 = 47; n = 0;
39732 while (++i$1 < 58) {
39733     d3keybinding.keyCodes[n] = i$1;
39734     ++n;
39735 }
39736
39737 // F1-F25
39738 i$1 = 111; n = 1;
39739 while (++i$1 < 136) {
39740     d3keybinding.keyCodes['f' + n] = i$1;
39741     ++n;
39742 }
39743
39744 // a-z
39745 i$1 = 64;
39746 while (++i$1 < 91) {
39747     d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39748 }
39749
39750 function tooltip() {
39751   var tooltip = function(selection$$1) {
39752       selection$$1.each(setup);
39753     },
39754     animation = utilFunctor(false),
39755     html$$1 = utilFunctor(false),
39756     title = function() {
39757       var title = this.getAttribute('data-original-title');
39758       if (title) {
39759         return title;
39760       } else {
39761         title = this.getAttribute('title');
39762         this.removeAttribute('title');
39763         this.setAttribute('data-original-title', title);
39764       }
39765       return title;
39766     },
39767     over = 'mouseenter.tooltip',
39768     out = 'mouseleave.tooltip',
39769     placement = utilFunctor('top');
39770
39771
39772   tooltip.title = function(_) {
39773     if (arguments.length) {
39774       title = utilFunctor(_);
39775       return tooltip;
39776     } else {
39777       return title;
39778     }
39779   };
39780
39781
39782   tooltip.html = function(_) {
39783     if (arguments.length) {
39784       html$$1 = utilFunctor(_);
39785       return tooltip;
39786     } else {
39787       return html$$1;
39788     }
39789   };
39790
39791
39792   tooltip.placement = function(_) {
39793     if (arguments.length) {
39794       placement = utilFunctor(_);
39795       return tooltip;
39796     } else {
39797       return placement;
39798     }
39799   };
39800
39801
39802   tooltip.show = function(selection$$1) {
39803     selection$$1.each(show);
39804   };
39805
39806
39807   tooltip.hide = function(selection$$1) {
39808     selection$$1.each(hide);
39809   };
39810
39811
39812   tooltip.toggle = function(selection$$1) {
39813     selection$$1.each(toggle);
39814   };
39815
39816
39817   tooltip.destroy = function(selection$$1) {
39818     selection$$1
39819       .on(over, null)
39820       .on(out, null)
39821       .attr('title', function() {
39822         return this.getAttribute('data-original-title') || this.getAttribute('title');
39823       })
39824       .attr('data-original-title', null)
39825       .selectAll('.tooltip')
39826       .remove();
39827   };
39828
39829
39830   function setup() {
39831     var root = select(this),
39832         animate = animation.apply(this, arguments),
39833         tip = root.selectAll('.tooltip').data([0]);
39834
39835     var enter = tip.enter()
39836       .append('div')
39837       .attr('class', 'tooltip');
39838
39839     enter
39840       .append('div')
39841       .attr('class', 'tooltip-arrow');
39842
39843     enter
39844       .append('div')
39845       .attr('class', 'tooltip-inner');
39846
39847     tip = enter
39848       .merge(tip);
39849
39850     if (animate) {
39851       tip.classed('fade', true);
39852     }
39853
39854     var place = placement.apply(this, arguments);
39855     tip.classed(place, true);
39856
39857     root.on(over, show);
39858     root.on(out, hide);
39859   }
39860
39861
39862   function show() {
39863     var root = select(this),
39864       content = title.apply(this, arguments),
39865       tip = root.selectAll('.tooltip')
39866         .classed('in', true),
39867       markup = html$$1.apply(this, arguments);
39868
39869     tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39870     var place = placement.apply(this, arguments),
39871       outer = getPosition(root.node()),
39872       inner = getPosition(tip.node()),
39873       pos;
39874
39875     switch (place) {
39876       case 'top':
39877         pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39878         break;
39879       case 'right':
39880         pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39881         break;
39882       case 'left':
39883         pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39884         break;
39885       case 'bottom':
39886         pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39887         break;
39888     }
39889
39890     if (pos) {
39891       tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39892     } else {
39893       tip.style('left', null).style('top', null);
39894     }
39895
39896     this.tooltipVisible = true;
39897   }
39898
39899
39900   function hide() {
39901     select(this).selectAll('.tooltip')
39902       .classed('in', false);
39903
39904     this.tooltipVisible = false;
39905   }
39906
39907
39908   function toggle() {
39909     if (this.tooltipVisible) {
39910       hide.apply(this, arguments);
39911     } else {
39912       show.apply(this, arguments);
39913     }
39914   }
39915
39916   return tooltip;
39917 }
39918
39919
39920 function getPosition(node) {
39921   var mode = select(node).style('position');
39922   if (mode === 'absolute' || mode === 'static') {
39923     return {
39924       x: node.offsetLeft,
39925       y: node.offsetTop,
39926       w: node.offsetWidth,
39927       h: node.offsetHeight
39928     };
39929   } else {
39930     return {
39931       x: 0,
39932       y: 0,
39933       w: node.offsetWidth,
39934       h: node.offsetHeight
39935     };
39936   }
39937 }
39938
39939 function svgAreas$$1(projection, context) {
39940     // Patterns only work in Firefox when set directly on element.
39941     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39942     var patterns = {
39943         beach: 'beach',
39944         cemetery: 'cemetery',
39945         construction: 'construction',
39946         farm: 'farmland',
39947         farmland: 'farmland',
39948         grave_yard: 'cemetery',
39949         meadow: 'meadow',
39950         military: 'construction',
39951         orchard: 'orchard',
39952         sand: 'beach',
39953         scrub: 'scrub',
39954         wetland: 'wetland',
39955     };
39956
39957     var patternKeys = ['landuse', 'natural', 'amenity'];
39958
39959
39960     function setPattern(d) {
39961         for (var i = 0; i < patternKeys.length; i++) {
39962             if (d.tags.building && d.tags.building !== 'no') continue;
39963
39964             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39965                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39966                 return;
39967             }
39968         }
39969         this.style.fill = this.style.stroke = '';
39970     }
39971
39972
39973     return function drawAreas(selection$$1, graph, entities, filter) {
39974         var path$$1 = svgPath(projection, graph, true),
39975             areas = {},
39976             multipolygon;
39977
39978         for (var i = 0; i < entities.length; i++) {
39979             var entity = entities[i];
39980             if (entity.geometry(graph) !== 'area') continue;
39981
39982             multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
39983             if (multipolygon) {
39984                 areas[multipolygon.id] = {
39985                     entity: multipolygon.mergeTags(entity.tags),
39986                     area: Math.abs(entity.area(graph))
39987                 };
39988             } else if (!areas[entity.id]) {
39989                 areas[entity.id] = {
39990                     entity: entity,
39991                     area: Math.abs(entity.area(graph))
39992                 };
39993             }
39994         }
39995
39996         areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
39997         areas.sort(function areaSort(a, b) { return b.area - a.area; });
39998         areas = lodash.map(areas, 'entity');
39999
40000         var strokes = areas.filter(function(area$$1) {
40001             return area$$1.type === 'way';
40002         });
40003
40004         var data = {
40005             clip: areas,
40006             shadow: strokes,
40007             stroke: strokes,
40008             fill: areas
40009         };
40010
40011         var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
40012            .filter(filter)
40013            .data(data.clip, osmEntity$$1.key);
40014
40015         clipPaths.exit()
40016            .remove();
40017
40018         var clipPathsEnter = clipPaths.enter()
40019            .append('clipPath')
40020            .attr('class', 'clipPath')
40021            .attr('id', function(entity) { return entity.id + '-clippath'; });
40022
40023         clipPathsEnter
40024            .append('path');
40025
40026         clipPaths.merge(clipPathsEnter)
40027            .selectAll('path')
40028            .attr('d', path$$1);
40029
40030
40031         var layer = selection$$1.selectAll('.layer-areas');
40032
40033         var areagroup = layer
40034             .selectAll('g.areagroup')
40035             .data(['fill', 'shadow', 'stroke']);
40036
40037         areagroup = areagroup.enter()
40038             .append('g')
40039             .attr('class', function(d) { return 'areagroup area-' + d; })
40040             .merge(areagroup);
40041
40042         var paths = areagroup
40043             .selectAll('path')
40044             .filter(filter)
40045             .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
40046
40047         paths.exit()
40048             .remove();
40049
40050         var fills = selection$$1.selectAll('.area-fill path.area').nodes();
40051
40052         var bisect$$1 = bisector(function(node) {
40053             return -node.__data__.area(graph);
40054         }).left;
40055
40056         function sortedByArea(entity) {
40057             if (this._parent.__data__ === 'fill') {
40058                 return fills[bisect$$1(fills, -entity.area(graph))];
40059             }
40060         }
40061
40062         paths = paths.enter()
40063             .insert('path', sortedByArea)
40064             .merge(paths)
40065             .each(function(entity) {
40066                 var layer = this.parentNode.__data__;
40067
40068                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
40069
40070                 if (layer === 'fill') {
40071                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
40072                     setPattern.apply(this, arguments);
40073                 }
40074             })
40075             .call(svgTagClasses())
40076             .attr('d', path$$1);
40077     };
40078 }
40079
40080 function svgDebug(projection, context) {
40081
40082     function multipolygons(imagery) {
40083         return imagery.map(function(data$$1) {
40084             return {
40085                 type: 'MultiPolygon',
40086                 coordinates: [ data$$1.polygon ]
40087             };
40088         });
40089     }
40090
40091     function drawDebug(selection$$1) {
40092         var showsTile = context.getDebug('tile'),
40093             showsCollision = context.getDebug('collision'),
40094             showsImagery = context.getDebug('imagery'),
40095             showsImperial = context.getDebug('imperial'),
40096             showsDriveLeft = context.getDebug('driveLeft'),
40097             path$$1 = index$4(projection);
40098
40099
40100         var debugData = [];
40101         if (showsTile) {
40102             debugData.push({ class: 'red', label: 'tile' });
40103         }
40104         if (showsCollision) {
40105             debugData.push({ class: 'yellow', label: 'collision' });
40106         }
40107         if (showsImagery) {
40108             debugData.push({ class: 'orange', label: 'imagery' });
40109         }
40110         if (showsImperial) {
40111             debugData.push({ class: 'cyan', label: 'imperial' });
40112         }
40113         if (showsDriveLeft) {
40114             debugData.push({ class: 'green', label: 'driveLeft' });
40115         }
40116
40117
40118         var legend = select('#content')
40119             .selectAll('.debug-legend')
40120             .data(debugData.length ? [0] : []);
40121
40122         legend.exit()
40123             .remove();
40124
40125         legend = legend.enter()
40126             .append('div')
40127             .attr('class', 'fillD debug-legend')
40128             .merge(legend);
40129
40130
40131         var legendItems = legend.selectAll('.debug-legend-item')
40132             .data(debugData, function(d) { return d.label; });
40133
40134         legendItems.exit()
40135             .remove();
40136
40137         legendItems.enter()
40138             .append('span')
40139             .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
40140             .text(function(d) { return d.label; });
40141
40142
40143         var layer = selection$$1.selectAll('.layer-debug')
40144             .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
40145
40146         layer.exit()
40147             .remove();
40148
40149         layer = layer.enter()
40150             .append('g')
40151             .attr('class', 'layer-debug')
40152             .merge(layer);
40153
40154
40155         var extent$$1 = context.map().extent(),
40156             dataImagery = data.imagery || [],
40157             availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
40158                 if (!source.polygon) return false;
40159                 return source.polygon.some(function(polygon) {
40160                     return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
40161                 });
40162             }));
40163
40164         var imagery = layer.selectAll('path.debug-imagery')
40165             .data(showsImagery ? availableImagery : []);
40166
40167         imagery.exit()
40168             .remove();
40169
40170         imagery.enter()
40171             .append('path')
40172             .attr('class', 'debug-imagery debug orange');
40173
40174
40175         var imperial = layer
40176             .selectAll('path.debug-imperial')
40177             .data(showsImperial ? [dataImperial] : []);
40178
40179         imperial.exit()
40180             .remove();
40181
40182         imperial.enter()
40183             .append('path')
40184             .attr('class', 'debug-imperial debug cyan');
40185
40186
40187         var driveLeft = layer
40188             .selectAll('path.debug-drive-left')
40189             .data(showsDriveLeft ? [dataDriveLeft] : []);
40190
40191         driveLeft.exit()
40192             .remove();
40193
40194         driveLeft.enter()
40195             .append('path')
40196             .attr('class', 'debug-drive-left debug green');
40197
40198
40199         // update
40200         layer.selectAll('path')
40201             .attr('d', path$$1);
40202     }
40203
40204
40205     // This looks strange because `enabled` methods on other layers are
40206     // chainable getter/setters, and this one is just a getter.
40207     drawDebug.enabled = function() {
40208         if (!arguments.length) {
40209             return context.getDebug('tile') ||
40210                 context.getDebug('collision') ||
40211                 context.getDebug('imagery') ||
40212                 context.getDebug('imperial') ||
40213                 context.getDebug('driveLeft');
40214         } else {
40215             return this;
40216         }
40217     };
40218
40219
40220     return drawDebug;
40221 }
40222
40223 /*
40224     A standalone SVG element that contains only a `defs` sub-element. To be
40225     used once globally, since defs IDs must be unique within a document.
40226 */
40227 function svgDefs(context) {
40228
40229     function SVGSpriteDefinition(id, href) {
40230         return function(defs) {
40231             request(href)
40232                 .mimeType('image/svg+xml')
40233                 .response(function(xhr) { return xhr.responseXML; })
40234                 .get(function(err, svg) {
40235                     if (err) return;
40236                     defs.node().appendChild(
40237                         select(svg.documentElement).attr('id', id).node()
40238                     );
40239                 });
40240         };
40241     }
40242
40243
40244     return function drawDefs(selection$$1) {
40245         var defs = selection$$1.append('defs');
40246
40247         // marker
40248         defs.append('marker')
40249             .attr('id', 'oneway-marker')
40250             .attr('viewBox', '0 0 10 10')
40251             .attr('refY', 2.5)
40252             .attr('refX', 5)
40253             .attr('markerWidth', 2)
40254             .attr('markerHeight', 2)
40255             .attr('markerUnits', 'strokeWidth')
40256             .attr('orient', 'auto')
40257
40258             .append('path')
40259             .attr('class', 'oneway')
40260             .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')
40261             .attr('stroke', 'none')
40262             .attr('fill', '#000')
40263             .attr('opacity', '0.5');
40264
40265         // patterns
40266         var patterns = defs.selectAll('pattern')
40267             .data([
40268                 // pattern name, pattern image name
40269                 ['wetland', 'wetland'],
40270                 ['construction', 'construction'],
40271                 ['cemetery', 'cemetery'],
40272                 ['orchard', 'orchard'],
40273                 ['farmland', 'farmland'],
40274                 ['beach', 'dots'],
40275                 ['scrub', 'dots'],
40276                 ['meadow', 'dots']
40277             ])
40278             .enter()
40279             .append('pattern')
40280             .attr('id', function (d) {
40281                 return 'pattern-' + d[0];
40282             })
40283             .attr('width', 32)
40284             .attr('height', 32)
40285             .attr('patternUnits', 'userSpaceOnUse');
40286
40287         patterns.append('rect')
40288             .attr('x', 0)
40289             .attr('y', 0)
40290             .attr('width', 32)
40291             .attr('height', 32)
40292             .attr('class', function (d) {
40293                     return 'pattern-color-' + d[0];
40294             });
40295
40296         patterns.append('image')
40297             .attr('x', 0)
40298             .attr('y', 0)
40299             .attr('width', 32)
40300             .attr('height', 32)
40301             .attr('xlink:href', function (d) {
40302                 return context.imagePath('pattern/' + d[1] + '.png');
40303             });
40304
40305         // clip paths
40306         defs.selectAll()
40307             .data([12, 18, 20, 32, 45])
40308             .enter()
40309             .append('clipPath')
40310             .attr('id', function (d) {
40311                 return 'clip-square-' + d;
40312             })
40313             .append('rect')
40314             .attr('x', 0)
40315             .attr('y', 0)
40316             .attr('width', function (d) {
40317                 return d;
40318             })
40319             .attr('height', function (d) {
40320                 return d;
40321             });
40322
40323         defs.call(SVGSpriteDefinition(
40324             'iD-sprite',
40325             context.imagePath('iD-sprite.svg')));
40326
40327         defs.call(SVGSpriteDefinition(
40328             'maki-sprite',
40329             context.imagePath('maki-sprite.svg')));
40330     };
40331 }
40332
40333 var sax = createCommonjsModule(function (module, exports) {
40334 //[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]
40335 //[4a]          NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
40336 //[5]           Name       ::=          NameStartChar (NameChar)*
40337 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
40338 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
40339 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
40340 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
40341 //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(',')
40342
40343 //S_TAG,        S_ATTR, S_EQ,   S_V
40344 //S_ATTR_S,     S_E,    S_S,    S_C
40345 var S_TAG = 0;//tag name offerring
40346 var S_ATTR = 1;//attr name offerring 
40347 var S_ATTR_S=2;//attr name end and space offer
40348 var S_EQ = 3;//=space?
40349 var S_V = 4;//attr value(no quot value only)
40350 var S_E = 5;//attr value end and no space(quot end)
40351 var S_S = 6;//(attr value end || tag end ) && (space offer)
40352 var S_C = 7;//closed el<el />
40353
40354 function XMLReader(){
40355         
40356 }
40357
40358 XMLReader.prototype = {
40359         parse:function(source,defaultNSMap,entityMap){
40360                 var domBuilder = this.domBuilder;
40361                 domBuilder.startDocument();
40362                 _copy(defaultNSMap ,defaultNSMap = {});
40363                 parse(source,defaultNSMap,entityMap,
40364                                 domBuilder,this.errorHandler);
40365                 domBuilder.endDocument();
40366         }
40367 };
40368 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
40369   function fixedFromCharCode(code) {
40370                 // String.prototype.fromCharCode does not supports
40371                 // > 2 bytes unicode chars directly
40372                 if (code > 0xffff) {
40373                         code -= 0x10000;
40374                         var surrogate1 = 0xd800 + (code >> 10)
40375                                 , surrogate2 = 0xdc00 + (code & 0x3ff);
40376
40377                         return String.fromCharCode(surrogate1, surrogate2);
40378                 } else {
40379                         return String.fromCharCode(code);
40380                 }
40381         }
40382         function entityReplacer(a){
40383                 var k = a.slice(1,-1);
40384                 if(k in entityMap){
40385                         return entityMap[k]; 
40386                 }else if(k.charAt(0) === '#'){
40387                         return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
40388                 }else{
40389                         errorHandler.error('entity not found:'+a);
40390                         return a;
40391                 }
40392         }
40393         function appendText(end){//has some bugs
40394                 if(end>start){
40395                         var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
40396                         locator&&position(start);
40397                         domBuilder.characters(xt,0,end-start);
40398                         start = end;
40399                 }
40400         }
40401         function position(p,m){
40402                 while(p>=lineEnd && (m = linePattern.exec(source))){
40403                         lineStart = m.index;
40404                         lineEnd = lineStart + m[0].length;
40405                         locator.lineNumber++;
40406                         //console.log('line++:',locator,startPos,endPos)
40407                 }
40408                 locator.columnNumber = p-lineStart+1;
40409         }
40410         var lineStart = 0;
40411         var lineEnd = 0;
40412         var linePattern = /.+(?:\r\n?|\n)|.*$/g;
40413         var locator = domBuilder.locator;
40414         
40415         var parseStack = [{currentNSMap:defaultNSMapCopy}];
40416         var closeMap = {};
40417         var start = 0;
40418         while(true){
40419                 try{
40420                         var tagStart = source.indexOf('<',start);
40421                         if(tagStart<0){
40422                                 if(!source.substr(start).match(/^\s*$/)){
40423                                         var doc = domBuilder.document;
40424                                 var text = doc.createTextNode(source.substr(start));
40425                                 doc.appendChild(text);
40426                                 domBuilder.currentElement = text;
40427                                 }
40428                                 return;
40429                         }
40430                         if(tagStart>start){
40431                                 appendText(tagStart);
40432                         }
40433                         switch(source.charAt(tagStart+1)){
40434                         case '/':
40435                                 var end = source.indexOf('>',tagStart+3);
40436                                 var tagName = source.substring(tagStart+2,end);
40437                                 var config = parseStack.pop();
40438                                 var localNSMap = config.localNSMap;
40439                         if(config.tagName != tagName){
40440                             errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
40441                         }
40442                                 domBuilder.endElement(config.uri,config.localName,tagName);
40443                                 if(localNSMap){
40444                                         for(var prefix in localNSMap){
40445                                                 domBuilder.endPrefixMapping(prefix) ;
40446                                         }
40447                                 }
40448                                 end++;
40449                                 break;
40450                                 // end elment
40451                         case '?':// <?...?>
40452                                 locator&&position(tagStart);
40453                                 end = parseInstruction(source,tagStart,domBuilder);
40454                                 break;
40455                         case '!':// <!doctype,<![CDATA,<!--
40456                                 locator&&position(tagStart);
40457                                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
40458                                 break;
40459                         default:
40460                         
40461                                 locator&&position(tagStart);
40462                                 
40463                                 var el = new ElementAttributes();
40464                                 
40465                                 //elStartEnd
40466                                 var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
40467                                 var len = el.length;
40468                                 
40469                                 if(locator){
40470                                         if(len){
40471                                                 //attribute position fixed
40472                                                 for(var i = 0;i<len;i++){
40473                                                         var a = el[i];
40474                                                         position(a.offset);
40475                                                         a.offset = copyLocator(locator,{});
40476                                                 }
40477                                         }
40478                                         position(end);
40479                                 }
40480                                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
40481                                         el.closed = true;
40482                                         if(!entityMap.nbsp){
40483                                                 errorHandler.warning('unclosed xml attribute');
40484                                         }
40485                                 }
40486                                 appendElement(el,domBuilder,parseStack);
40487                                 
40488                                 
40489                                 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
40490                                         end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
40491                                 }else{
40492                                         end++;
40493                                 }
40494                         }
40495                 }catch(e){
40496                         errorHandler.error('element parse error: '+e);
40497                         end = -1;
40498                 }
40499                 if(end>start){
40500                         start = end;
40501                 }else{
40502                         //TODO: 这里有可能sax回退,有位置错误风险
40503                         appendText(Math.max(tagStart,start)+1);
40504                 }
40505         }
40506 }
40507 function copyLocator(f,t){
40508         t.lineNumber = f.lineNumber;
40509         t.columnNumber = f.columnNumber;
40510         return t;
40511 }
40512
40513 /**
40514  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40515  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40516  */
40517 function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
40518         var attrName;
40519         var value;
40520         var p = ++start;
40521         var s = S_TAG;//status
40522         while(true){
40523                 var c = source.charAt(p);
40524                 switch(c){
40525                 case '=':
40526                         if(s === S_ATTR){//attrName
40527                                 attrName = source.slice(start,p);
40528                                 s = S_EQ;
40529                         }else if(s === S_ATTR_S){
40530                                 s = S_EQ;
40531                         }else{
40532                                 //fatalError: equal must after attrName or space after attrName
40533                                 throw new Error('attribute equal must after attrName');
40534                         }
40535                         break;
40536                 case '\'':
40537                 case '"':
40538                         if(s === S_EQ){//equal
40539                                 start = p+1;
40540                                 p = source.indexOf(c,start);
40541                                 if(p>0){
40542                                         value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40543                                         el.add(attrName,value,start-1);
40544                                         s = S_E;
40545                                 }else{
40546                                         //fatalError: no end quot match
40547                                         throw new Error('attribute value no end \''+c+'\' match');
40548                                 }
40549                         }else if(s == S_V){
40550                                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40551                                 //console.log(attrName,value,start,p)
40552                                 el.add(attrName,value,start);
40553                                 //console.dir(el)
40554                                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40555                                 start = p+1;
40556                                 s = S_E;
40557                         }else{
40558                                 //fatalError: no equal before
40559                                 throw new Error('attribute value must after "="');
40560                         }
40561                         break;
40562                 case '/':
40563                         switch(s){
40564                         case S_TAG:
40565                                 el.setTagName(source.slice(start,p));
40566                         case S_E:
40567                         case S_S:
40568                         case S_C:
40569                                 s = S_C;
40570                                 el.closed = true;
40571                         case S_V:
40572                         case S_ATTR:
40573                         case S_ATTR_S:
40574                                 break;
40575                         //case S_EQ:
40576                         default:
40577                                 throw new Error("attribute invalid close char('/')")
40578                         }
40579                         break;
40580                 case ''://end document
40581                         //throw new Error('unexpected end of input')
40582                         errorHandler.error('unexpected end of input');
40583                 case '>':
40584                         switch(s){
40585                         case S_TAG:
40586                                 el.setTagName(source.slice(start,p));
40587                         case S_E:
40588                         case S_S:
40589                         case S_C:
40590                                 break;//normal
40591                         case S_V://Compatible state
40592                         case S_ATTR:
40593                                 value = source.slice(start,p);
40594                                 if(value.slice(-1) === '/'){
40595                                         el.closed  = true;
40596                                         value = value.slice(0,-1);
40597                                 }
40598                         case S_ATTR_S:
40599                                 if(s === S_ATTR_S){
40600                                         value = attrName;
40601                                 }
40602                                 if(s == S_V){
40603                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40604                                         el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40605                                 }else{
40606                                         errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40607                                         el.add(value,value,start);
40608                                 }
40609                                 break;
40610                         case S_EQ:
40611                                 throw new Error('attribute value missed!!');
40612                         }
40613 //                      console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40614                         return p;
40615                 /*xml space '\x20' | #x9 | #xD | #xA; */
40616                 case '\u0080':
40617                         c = ' ';
40618                 default:
40619                         if(c<= ' '){//space
40620                                 switch(s){
40621                                 case S_TAG:
40622                                         el.setTagName(source.slice(start,p));//tagName
40623                                         s = S_S;
40624                                         break;
40625                                 case S_ATTR:
40626                                         attrName = source.slice(start,p);
40627                                         s = S_ATTR_S;
40628                                         break;
40629                                 case S_V:
40630                                         var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40631                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40632                                         el.add(attrName,value,start);
40633                                 case S_E:
40634                                         s = S_S;
40635                                         break;
40636                                 //case S_S:
40637                                 //case S_EQ:
40638                                 //case S_ATTR_S:
40639                                 //      void();break;
40640                                 //case S_C:
40641                                         //ignore warning
40642                                 }
40643                         }else{//not space
40644 //S_TAG,        S_ATTR, S_EQ,   S_V
40645 //S_ATTR_S,     S_E,    S_S,    S_C
40646                                 switch(s){
40647                                 //case S_TAG:void();break;
40648                                 //case S_ATTR:void();break;
40649                                 //case S_V:void();break;
40650                                 case S_ATTR_S:
40651                                         errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!');
40652                                         el.add(attrName,attrName,start);
40653                                         start = p;
40654                                         s = S_ATTR;
40655                                         break;
40656                                 case S_E:
40657                                         errorHandler.warning('attribute space is required"'+attrName+'"!!');
40658                                 case S_S:
40659                                         s = S_ATTR;
40660                                         start = p;
40661                                         break;
40662                                 case S_EQ:
40663                                         s = S_V;
40664                                         start = p;
40665                                         break;
40666                                 case S_C:
40667                                         throw new Error("elements closed character '/' and '>' must be connected to");
40668                                 }
40669                         }
40670                 }
40671                 p++;
40672         }
40673 }
40674 /**
40675  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40676  */
40677 function appendElement(el,domBuilder,parseStack){
40678         var tagName = el.tagName;
40679         var localNSMap = null;
40680         var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40681         var i = el.length;
40682         while(i--){
40683                 var a = el[i];
40684                 var qName = a.qName;
40685                 var value = a.value;
40686                 var nsp = qName.indexOf(':');
40687                 if(nsp>0){
40688                         var prefix = a.prefix = qName.slice(0,nsp);
40689                         var localName = qName.slice(nsp+1);
40690                         var nsPrefix = prefix === 'xmlns' && localName;
40691                 }else{
40692                         localName = qName;
40693                         prefix = null;
40694                         nsPrefix = qName === 'xmlns' && '';
40695                 }
40696                 //can not set prefix,because prefix !== ''
40697                 a.localName = localName ;
40698                 //prefix == null for no ns prefix attribute 
40699                 if(nsPrefix !== false){//hack!!
40700                         if(localNSMap == null){
40701                                 localNSMap = {};
40702                                 //console.log(currentNSMap,0)
40703                                 _copy(currentNSMap,currentNSMap={});
40704                                 //console.log(currentNSMap,1)
40705                         }
40706                         currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40707                         a.uri = 'http://www.w3.org/2000/xmlns/';
40708                         domBuilder.startPrefixMapping(nsPrefix, value); 
40709                 }
40710         }
40711         var i = el.length;
40712         while(i--){
40713                 a = el[i];
40714                 var prefix = a.prefix;
40715                 if(prefix){//no prefix attribute has no namespace
40716                         if(prefix === 'xml'){
40717                                 a.uri = 'http://www.w3.org/XML/1998/namespace';
40718                         }if(prefix !== 'xmlns'){
40719                                 a.uri = currentNSMap[prefix];
40720                                 
40721                                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40722                         }
40723                 }
40724         }
40725         var nsp = tagName.indexOf(':');
40726         if(nsp>0){
40727                 prefix = el.prefix = tagName.slice(0,nsp);
40728                 localName = el.localName = tagName.slice(nsp+1);
40729         }else{
40730                 prefix = null;//important!!
40731                 localName = el.localName = tagName;
40732         }
40733         //no prefix element has default namespace
40734         var ns = el.uri = currentNSMap[prefix || ''];
40735         domBuilder.startElement(ns,localName,tagName,el);
40736         //endPrefixMapping and startPrefixMapping have not any help for dom builder
40737         //localNSMap = null
40738         if(el.closed){
40739                 domBuilder.endElement(ns,localName,tagName);
40740                 if(localNSMap){
40741                         for(prefix in localNSMap){
40742                                 domBuilder.endPrefixMapping(prefix); 
40743                         }
40744                 }
40745         }else{
40746                 el.currentNSMap = currentNSMap;
40747                 el.localNSMap = localNSMap;
40748                 parseStack.push(el);
40749         }
40750 }
40751 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40752         if(/^(?:script|textarea)$/i.test(tagName)){
40753                 var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
40754                 var text = source.substring(elStartEnd+1,elEndStart);
40755                 if(/[&<]/.test(text)){
40756                         if(/^script$/i.test(tagName)){
40757                                 //if(!/\]\]>/.test(text)){
40758                                         //lexHandler.startCDATA();
40759                                         domBuilder.characters(text,0,text.length);
40760                                         //lexHandler.endCDATA();
40761                                         return elEndStart;
40762                                 //}
40763                         }//}else{//text area
40764                                 text = text.replace(/&#?\w+;/g,entityReplacer);
40765                                 domBuilder.characters(text,0,text.length);
40766                                 return elEndStart;
40767                         //}
40768                         
40769                 }
40770         }
40771         return elStartEnd+1;
40772 }
40773 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40774         //if(tagName in closeMap){
40775         var pos = closeMap[tagName];
40776         if(pos == null){
40777                 //console.log(tagName)
40778                 pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>');
40779         }
40780         return pos<elStartEnd;
40781         //} 
40782 }
40783 function _copy(source,target){
40784         for(var n in source){target[n] = source[n];}
40785 }
40786 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40787         var next= source.charAt(start+2);
40788         switch(next){
40789         case '-':
40790                 if(source.charAt(start + 3) === '-'){
40791                         var end = source.indexOf('-->',start+4);
40792                         //append comment source.substring(4,end)//<!--
40793                         if(end>start){
40794                                 domBuilder.comment(source,start+4,end-start-4);
40795                                 return end+3;
40796                         }else{
40797                                 errorHandler.error("Unclosed comment");
40798                                 return -1;
40799                         }
40800                 }else{
40801                         //error
40802                         return -1;
40803                 }
40804         default:
40805                 if(source.substr(start+3,6) == 'CDATA['){
40806                         var end = source.indexOf(']]>',start+9);
40807                         domBuilder.startCDATA();
40808                         domBuilder.characters(source,start+9,end-start-9);
40809                         domBuilder.endCDATA(); 
40810                         return end+3;
40811                 }
40812                 //<!DOCTYPE
40813                 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
40814                 var matchs = split(source,start);
40815                 var len = matchs.length;
40816                 if(len>1 && /!doctype/i.test(matchs[0][0])){
40817                         var name = matchs[1][0];
40818                         var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40819                         var sysid = len>4 && matchs[4][0];
40820                         var lastMatch = matchs[len-1];
40821                         domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40822                                         sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40823                         domBuilder.endDTD();
40824                         
40825                         return lastMatch.index+lastMatch[0].length
40826                 }
40827         }
40828         return -1;
40829 }
40830
40831
40832
40833 function parseInstruction(source,start,domBuilder){
40834         var end = source.indexOf('?>',start);
40835         if(end){
40836                 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40837                 if(match){
40838                         var len = match[0].length;
40839                         domBuilder.processingInstruction(match[1], match[2]) ;
40840                         return end+2;
40841                 }else{//error
40842                         return -1;
40843                 }
40844         }
40845         return -1;
40846 }
40847
40848 /**
40849  * @param source
40850  */
40851 function ElementAttributes(source){
40852         
40853 }
40854 ElementAttributes.prototype = {
40855         setTagName:function(tagName){
40856                 if(!tagNamePattern.test(tagName)){
40857                         throw new Error('invalid tagName:'+tagName)
40858                 }
40859                 this.tagName = tagName;
40860         },
40861         add:function(qName,value,offset){
40862                 if(!tagNamePattern.test(qName)){
40863                         throw new Error('invalid attribute:'+qName)
40864                 }
40865                 this[this.length++] = {qName:qName,value:value,offset:offset};
40866         },
40867         length:0,
40868         getLocalName:function(i){return this[i].localName},
40869         getOffset:function(i){return this[i].offset},
40870         getQName:function(i){return this[i].qName},
40871         getURI:function(i){return this[i].uri},
40872         getValue:function(i){return this[i].value}
40873 //      ,getIndex:function(uri, localName)){
40874 //              if(localName){
40875 //                      
40876 //              }else{
40877 //                      var qName = uri
40878 //              }
40879 //      },
40880 //      getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40881 //      getType:function(uri,localName){}
40882 //      getType:function(i){},
40883 };
40884
40885
40886
40887
40888 function _set_proto_(thiz,parent){
40889         thiz.__proto__ = parent;
40890         return thiz;
40891 }
40892 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40893         _set_proto_ = function(thiz,parent){
40894                 function p(){}
40895                 p.prototype = parent;
40896                 p = new p();
40897                 for(parent in thiz){
40898                         p[parent] = thiz[parent];
40899                 }
40900                 return p;
40901         };
40902 }
40903
40904 function split(source,start){
40905         var match;
40906         var buf = [];
40907         var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40908         reg.lastIndex = start;
40909         reg.exec(source);//skip <
40910         while(match = reg.exec(source)){
40911                 buf.push(match);
40912                 if(match[1])return buf;
40913         }
40914 }
40915
40916 if(typeof commonjsRequire == 'function'){
40917         exports.XMLReader = XMLReader;
40918 }
40919 });
40920
40921 var dom = createCommonjsModule(function (module, exports) {
40922 /*
40923  * DOM Level 2
40924  * Object DOMException
40925  * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40926  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40927  */
40928
40929 function copy(src,dest){
40930         for(var p in src){
40931                 dest[p] = src[p];
40932         }
40933 }
40934 /**
40935 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
40936 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
40937  */
40938 function _extends(Class,Super){
40939         var pt = Class.prototype;
40940         if(Object.create){
40941                 var ppt = Object.create(Super.prototype);
40942                 pt.__proto__ = ppt;
40943         }
40944         if(!(pt instanceof Super)){
40945                 function t(){}
40946                 t.prototype = Super.prototype;
40947                 t = new t();
40948                 copy(pt,t);
40949                 Class.prototype = pt = t;
40950         }
40951         if(pt.constructor != Class){
40952                 if(typeof Class != 'function'){
40953                         console.error("unknow Class:"+Class);
40954                 }
40955                 pt.constructor = Class;
40956         }
40957 }
40958 var htmlns = 'http://www.w3.org/1999/xhtml';
40959 // Node Types
40960 var NodeType = {};
40961 var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
40962 var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
40963 var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
40964 var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
40965 var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
40966 var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
40967 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
40968 var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
40969 var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
40970 var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
40971 var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
40972 var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;
40973
40974 // ExceptionCode
40975 var ExceptionCode = {};
40976 var ExceptionMessage = {};
40977 var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
40978 var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
40979 var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
40980 var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
40981 var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
40982 var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
40983 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
40984 var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
40985 var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
40986 var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
40987 //level2
40988 var INVALID_STATE_ERR           = ExceptionCode.INVALID_STATE_ERR               = ((ExceptionMessage[11]="Invalid state"),11);
40989 var SYNTAX_ERR                  = ExceptionCode.SYNTAX_ERR                      = ((ExceptionMessage[12]="Syntax error"),12);
40990 var INVALID_MODIFICATION_ERR    = ExceptionCode.INVALID_MODIFICATION_ERR        = ((ExceptionMessage[13]="Invalid modification"),13);
40991 var NAMESPACE_ERR               = ExceptionCode.NAMESPACE_ERR                   = ((ExceptionMessage[14]="Invalid namespace"),14);
40992 var INVALID_ACCESS_ERR          = ExceptionCode.INVALID_ACCESS_ERR              = ((ExceptionMessage[15]="Invalid access"),15);
40993
40994
40995 function DOMException(code, message) {
40996         if(message instanceof Error){
40997                 var error = message;
40998         }else{
40999                 error = this;
41000                 Error.call(this, ExceptionMessage[code]);
41001                 this.message = ExceptionMessage[code];
41002                 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
41003         }
41004         error.code = code;
41005         if(message) this.message = this.message + ": " + message;
41006         return error;
41007 }
41008 DOMException.prototype = Error.prototype;
41009 copy(ExceptionCode,DOMException);
41010 /**
41011  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
41012  * 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.
41013  * The items in the NodeList are accessible via an integral index, starting from 0.
41014  */
41015 function NodeList() {
41016 }
41017 NodeList.prototype = {
41018         /**
41019          * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
41020          * @standard level1
41021          */
41022         length:0, 
41023         /**
41024          * 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.
41025          * @standard level1
41026          * @param index  unsigned long 
41027          *   Index into the collection.
41028          * @return Node
41029          *      The node at the indexth position in the NodeList, or null if that is not a valid index. 
41030          */
41031         item: function(index) {
41032                 return this[index] || null;
41033         },
41034         toString:function(){
41035                 for(var buf = [], i = 0;i<this.length;i++){
41036                         serializeToString(this[i],buf);
41037                 }
41038                 return buf.join('');
41039         }
41040 };
41041 function LiveNodeList(node,refresh){
41042         this._node = node;
41043         this._refresh = refresh;
41044         _updateLiveList(this);
41045 }
41046 function _updateLiveList(list){
41047         var inc = list._node._inc || list._node.ownerDocument._inc;
41048         if(list._inc != inc){
41049                 var ls = list._refresh(list._node);
41050                 //console.log(ls.length)
41051                 __set__(list,'length',ls.length);
41052                 copy(ls,list);
41053                 list._inc = inc;
41054         }
41055 }
41056 LiveNodeList.prototype.item = function(i){
41057         _updateLiveList(this);
41058         return this[i];
41059 };
41060
41061 _extends(LiveNodeList,NodeList);
41062 /**
41063  * 
41064  * 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.
41065  * NamedNodeMap objects in the DOM are live.
41066  * used for attributes or DocumentType entities 
41067  */
41068 function NamedNodeMap() {
41069 }
41070
41071 function _findNodeIndex(list,node){
41072         var i = list.length;
41073         while(i--){
41074                 if(list[i] === node){return i}
41075         }
41076 }
41077
41078 function _addNamedNode(el,list,newAttr,oldAttr){
41079         if(oldAttr){
41080                 list[_findNodeIndex(list,oldAttr)] = newAttr;
41081         }else{
41082                 list[list.length++] = newAttr;
41083         }
41084         if(el){
41085                 newAttr.ownerElement = el;
41086                 var doc = el.ownerDocument;
41087                 if(doc){
41088                         oldAttr && _onRemoveAttribute(doc,el,oldAttr);
41089                         _onAddAttribute(doc,el,newAttr);
41090                 }
41091         }
41092 }
41093 function _removeNamedNode(el,list,attr){
41094         var i = _findNodeIndex(list,attr);
41095         if(i>=0){
41096                 var lastIndex = list.length-1;
41097                 while(i<lastIndex){
41098                         list[i] = list[++i];
41099                 }
41100                 list.length = lastIndex;
41101                 if(el){
41102                         var doc = el.ownerDocument;
41103                         if(doc){
41104                                 _onRemoveAttribute(doc,el,attr);
41105                                 attr.ownerElement = null;
41106                         }
41107                 }
41108         }else{
41109                 throw DOMException(NOT_FOUND_ERR,new Error())
41110         }
41111 }
41112 NamedNodeMap.prototype = {
41113         length:0,
41114         item:NodeList.prototype.item,
41115         getNamedItem: function(key) {
41116 //              if(key.indexOf(':')>0 || key == 'xmlns'){
41117 //                      return null;
41118 //              }
41119                 var i = this.length;
41120                 while(i--){
41121                         var attr = this[i];
41122                         if(attr.nodeName == key){
41123                                 return attr;
41124                         }
41125                 }
41126         },
41127         setNamedItem: function(attr) {
41128                 var el = attr.ownerElement;
41129                 if(el && el!=this._ownerElement){
41130                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
41131                 }
41132                 var oldAttr = this.getNamedItem(attr.nodeName);
41133                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41134                 return oldAttr;
41135         },
41136         /* returns Node */
41137         setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
41138                 var el = attr.ownerElement, oldAttr;
41139                 if(el && el!=this._ownerElement){
41140                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
41141                 }
41142                 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
41143                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41144                 return oldAttr;
41145         },
41146
41147         /* returns Node */
41148         removeNamedItem: function(key) {
41149                 var attr = this.getNamedItem(key);
41150                 _removeNamedNode(this._ownerElement,this,attr);
41151                 return attr;
41152                 
41153                 
41154         },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
41155         
41156         //for level2
41157         removeNamedItemNS:function(namespaceURI,localName){
41158                 var attr = this.getNamedItemNS(namespaceURI,localName);
41159                 _removeNamedNode(this._ownerElement,this,attr);
41160                 return attr;
41161         },
41162         getNamedItemNS: function(namespaceURI, localName) {
41163                 var i = this.length;
41164                 while(i--){
41165                         var node = this[i];
41166                         if(node.localName == localName && node.namespaceURI == namespaceURI){
41167                                 return node;
41168                         }
41169                 }
41170                 return null;
41171         }
41172 };
41173 /**
41174  * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
41175  */
41176 function DOMImplementation(/* Object */ features) {
41177         this._features = {};
41178         if (features) {
41179                 for (var feature in features) {
41180                          this._features = features[feature];
41181                 }
41182         }
41183 }
41184
41185 DOMImplementation.prototype = {
41186         hasFeature: function(/* string */ feature, /* string */ version) {
41187                 var versions = this._features[feature.toLowerCase()];
41188                 if (versions && (!version || version in versions)) {
41189                         return true;
41190                 } else {
41191                         return false;
41192                 }
41193         },
41194         // Introduced in DOM Level 2:
41195         createDocument:function(namespaceURI,  qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
41196                 var doc = new Document();
41197                 doc.implementation = this;
41198                 doc.childNodes = new NodeList();
41199                 doc.doctype = doctype;
41200                 if(doctype){
41201                         doc.appendChild(doctype);
41202                 }
41203                 if(qualifiedName){
41204                         var root = doc.createElementNS(namespaceURI,qualifiedName);
41205                         doc.appendChild(root);
41206                 }
41207                 return doc;
41208         },
41209         // Introduced in DOM Level 2:
41210         createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
41211                 var node = new DocumentType();
41212                 node.name = qualifiedName;
41213                 node.nodeName = qualifiedName;
41214                 node.publicId = publicId;
41215                 node.systemId = systemId;
41216                 // Introduced in DOM Level 2:
41217                 //readonly attribute DOMString        internalSubset;
41218                 
41219                 //TODO:..
41220                 //  readonly attribute NamedNodeMap     entities;
41221                 //  readonly attribute NamedNodeMap     notations;
41222                 return node;
41223         }
41224 };
41225
41226
41227 /**
41228  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
41229  */
41230
41231 function Node() {
41232 }
41233
41234 Node.prototype = {
41235         firstChild : null,
41236         lastChild : null,
41237         previousSibling : null,
41238         nextSibling : null,
41239         attributes : null,
41240         parentNode : null,
41241         childNodes : null,
41242         ownerDocument : null,
41243         nodeValue : null,
41244         namespaceURI : null,
41245         prefix : null,
41246         localName : null,
41247         // Modified in DOM Level 2:
41248         insertBefore:function(newChild, refChild){//raises 
41249                 return _insertBefore(this,newChild,refChild);
41250         },
41251         replaceChild:function(newChild, oldChild){//raises 
41252                 this.insertBefore(newChild,oldChild);
41253                 if(oldChild){
41254                         this.removeChild(oldChild);
41255                 }
41256         },
41257         removeChild:function(oldChild){
41258                 return _removeChild(this,oldChild);
41259         },
41260         appendChild:function(newChild){
41261                 return this.insertBefore(newChild,null);
41262         },
41263         hasChildNodes:function(){
41264                 return this.firstChild != null;
41265         },
41266         cloneNode:function(deep){
41267                 return cloneNode(this.ownerDocument||this,this,deep);
41268         },
41269         // Modified in DOM Level 2:
41270         normalize:function(){
41271                 var child = this.firstChild;
41272                 while(child){
41273                         var next = child.nextSibling;
41274                         if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
41275                                 this.removeChild(next);
41276                                 child.appendData(next.data);
41277                         }else{
41278                                 child.normalize();
41279                                 child = next;
41280                         }
41281                 }
41282         },
41283         // Introduced in DOM Level 2:
41284         isSupported:function(feature, version){
41285                 return this.ownerDocument.implementation.hasFeature(feature,version);
41286         },
41287     // Introduced in DOM Level 2:
41288     hasAttributes:function(){
41289         return this.attributes.length>0;
41290     },
41291     lookupPrefix:function(namespaceURI){
41292         var el = this;
41293         while(el){
41294                 var map = el._nsMap;
41295                 //console.dir(map)
41296                 if(map){
41297                         for(var n in map){
41298                                 if(map[n] == namespaceURI){
41299                                         return n;
41300                                 }
41301                         }
41302                 }
41303                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41304         }
41305         return null;
41306     },
41307     // Introduced in DOM Level 3:
41308     lookupNamespaceURI:function(prefix){
41309         var el = this;
41310         while(el){
41311                 var map = el._nsMap;
41312                 //console.dir(map)
41313                 if(map){
41314                         if(prefix in map){
41315                                 return map[prefix] ;
41316                         }
41317                 }
41318                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41319         }
41320         return null;
41321     },
41322     // Introduced in DOM Level 3:
41323     isDefaultNamespace:function(namespaceURI){
41324         var prefix = this.lookupPrefix(namespaceURI);
41325         return prefix == null;
41326     }
41327 };
41328
41329
41330 function _xmlEncoder(c){
41331         return c == '<' && '&lt;' ||
41332          c == '>' && '&gt;' ||
41333          c == '&' && '&amp;' ||
41334          c == '"' && '&quot;' ||
41335          '&#'+c.charCodeAt()+';'
41336 }
41337
41338
41339 copy(NodeType,Node);
41340 copy(NodeType,Node.prototype);
41341
41342 /**
41343  * @param callback return true for continue,false for break
41344  * @return boolean true: break visit;
41345  */
41346 function _visitNode(node,callback){
41347         if(callback(node)){
41348                 return true;
41349         }
41350         if(node = node.firstChild){
41351                 do{
41352                         if(_visitNode(node,callback)){return true}
41353         }while(node=node.nextSibling)
41354     }
41355 }
41356
41357
41358
41359 function Document(){
41360 }
41361 function _onAddAttribute(doc,el,newAttr){
41362         doc && doc._inc++;
41363         var ns = newAttr.namespaceURI;
41364         if(ns == 'http://www.w3.org/2000/xmlns/'){
41365                 //update namespace
41366                 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
41367         }
41368 }
41369 function _onRemoveAttribute(doc,el,newAttr,remove){
41370         doc && doc._inc++;
41371         var ns = newAttr.namespaceURI;
41372         if(ns == 'http://www.w3.org/2000/xmlns/'){
41373                 //update namespace
41374                 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
41375         }
41376 }
41377 function _onUpdateChild(doc,el,newChild){
41378         if(doc && doc._inc){
41379                 doc._inc++;
41380                 //update childNodes
41381                 var cs = el.childNodes;
41382                 if(newChild){
41383                         cs[cs.length++] = newChild;
41384                 }else{
41385                         //console.log(1)
41386                         var child = el.firstChild;
41387                         var i = 0;
41388                         while(child){
41389                                 cs[i++] = child;
41390                                 child =child.nextSibling;
41391                         }
41392                         cs.length = i;
41393                 }
41394         }
41395 }
41396
41397 /**
41398  * attributes;
41399  * children;
41400  * 
41401  * writeable properties:
41402  * nodeValue,Attr:value,CharacterData:data
41403  * prefix
41404  */
41405 function _removeChild(parentNode,child){
41406         var previous = child.previousSibling;
41407         var next = child.nextSibling;
41408         if(previous){
41409                 previous.nextSibling = next;
41410         }else{
41411                 parentNode.firstChild = next;
41412         }
41413         if(next){
41414                 next.previousSibling = previous;
41415         }else{
41416                 parentNode.lastChild = previous;
41417         }
41418         _onUpdateChild(parentNode.ownerDocument,parentNode);
41419         return child;
41420 }
41421 /**
41422  * preformance key(refChild == null)
41423  */
41424 function _insertBefore(parentNode,newChild,nextChild){
41425         var cp = newChild.parentNode;
41426         if(cp){
41427                 cp.removeChild(newChild);//remove and update
41428         }
41429         if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41430                 var newFirst = newChild.firstChild;
41431                 if (newFirst == null) {
41432                         return newChild;
41433                 }
41434                 var newLast = newChild.lastChild;
41435         }else{
41436                 newFirst = newLast = newChild;
41437         }
41438         var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
41439
41440         newFirst.previousSibling = pre;
41441         newLast.nextSibling = nextChild;
41442         
41443         
41444         if(pre){
41445                 pre.nextSibling = newFirst;
41446         }else{
41447                 parentNode.firstChild = newFirst;
41448         }
41449         if(nextChild == null){
41450                 parentNode.lastChild = newLast;
41451         }else{
41452                 nextChild.previousSibling = newLast;
41453         }
41454         do{
41455                 newFirst.parentNode = parentNode;
41456         }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
41457         _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
41458         //console.log(parentNode.lastChild.nextSibling == null)
41459         if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
41460                 newChild.firstChild = newChild.lastChild = null;
41461         }
41462         return newChild;
41463 }
41464 function _appendSingleChild(parentNode,newChild){
41465         var cp = newChild.parentNode;
41466         if(cp){
41467                 var pre = parentNode.lastChild;
41468                 cp.removeChild(newChild);//remove and update
41469                 var pre = parentNode.lastChild;
41470         }
41471         var pre = parentNode.lastChild;
41472         newChild.parentNode = parentNode;
41473         newChild.previousSibling = pre;
41474         newChild.nextSibling = null;
41475         if(pre){
41476                 pre.nextSibling = newChild;
41477         }else{
41478                 parentNode.firstChild = newChild;
41479         }
41480         parentNode.lastChild = newChild;
41481         _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
41482         return newChild;
41483         //console.log("__aa",parentNode.lastChild.nextSibling == null)
41484 }
41485 Document.prototype = {
41486         //implementation : null,
41487         nodeName :  '#document',
41488         nodeType :  DOCUMENT_NODE,
41489         doctype :  null,
41490         documentElement :  null,
41491         _inc : 1,
41492         
41493         insertBefore :  function(newChild, refChild){//raises 
41494                 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
41495                         var child = newChild.firstChild;
41496                         while(child){
41497                                 var next = child.nextSibling;
41498                                 this.insertBefore(child,refChild);
41499                                 child = next;
41500                         }
41501                         return newChild;
41502                 }
41503                 if(this.documentElement == null && newChild.nodeType == 1){
41504                         this.documentElement = newChild;
41505                 }
41506                 
41507                 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41508         },
41509         removeChild :  function(oldChild){
41510                 if(this.documentElement == oldChild){
41511                         this.documentElement = null;
41512                 }
41513                 return _removeChild(this,oldChild);
41514         },
41515         // Introduced in DOM Level 2:
41516         importNode : function(importedNode,deep){
41517                 return importNode(this,importedNode,deep);
41518         },
41519         // Introduced in DOM Level 2:
41520         getElementById :        function(id){
41521                 var rtv = null;
41522                 _visitNode(this.documentElement,function(node){
41523                         if(node.nodeType == 1){
41524                                 if(node.getAttribute('id') == id){
41525                                         rtv = node;
41526                                         return true;
41527                                 }
41528                         }
41529                 });
41530                 return rtv;
41531         },
41532         
41533         //document factory method:
41534         createElement : function(tagName){
41535                 var node = new Element();
41536                 node.ownerDocument = this;
41537                 node.nodeName = tagName;
41538                 node.tagName = tagName;
41539                 node.childNodes = new NodeList();
41540                 var attrs       = node.attributes = new NamedNodeMap();
41541                 attrs._ownerElement = node;
41542                 return node;
41543         },
41544         createDocumentFragment :        function(){
41545                 var node = new DocumentFragment();
41546                 node.ownerDocument = this;
41547                 node.childNodes = new NodeList();
41548                 return node;
41549         },
41550         createTextNode :        function(data){
41551                 var node = new Text();
41552                 node.ownerDocument = this;
41553                 node.appendData(data);
41554                 return node;
41555         },
41556         createComment : function(data){
41557                 var node = new Comment();
41558                 node.ownerDocument = this;
41559                 node.appendData(data);
41560                 return node;
41561         },
41562         createCDATASection :    function(data){
41563                 var node = new CDATASection();
41564                 node.ownerDocument = this;
41565                 node.appendData(data);
41566                 return node;
41567         },
41568         createProcessingInstruction :   function(target,data){
41569                 var node = new ProcessingInstruction();
41570                 node.ownerDocument = this;
41571                 node.tagName = node.target = target;
41572                 node.nodeValue= node.data = data;
41573                 return node;
41574         },
41575         createAttribute :       function(name){
41576                 var node = new Attr();
41577                 node.ownerDocument      = this;
41578                 node.name = name;
41579                 node.nodeName   = name;
41580                 node.localName = name;
41581                 node.specified = true;
41582                 return node;
41583         },
41584         createEntityReference : function(name){
41585                 var node = new EntityReference();
41586                 node.ownerDocument      = this;
41587                 node.nodeName   = name;
41588                 return node;
41589         },
41590         // Introduced in DOM Level 2:
41591         createElementNS :       function(namespaceURI,qualifiedName){
41592                 var node = new Element();
41593                 var pl = qualifiedName.split(':');
41594                 var attrs       = node.attributes = new NamedNodeMap();
41595                 node.childNodes = new NodeList();
41596                 node.ownerDocument = this;
41597                 node.nodeName = qualifiedName;
41598                 node.tagName = qualifiedName;
41599                 node.namespaceURI = namespaceURI;
41600                 if(pl.length == 2){
41601                         node.prefix = pl[0];
41602                         node.localName = pl[1];
41603                 }else{
41604                         //el.prefix = null;
41605                         node.localName = qualifiedName;
41606                 }
41607                 attrs._ownerElement = node;
41608                 return node;
41609         },
41610         // Introduced in DOM Level 2:
41611         createAttributeNS :     function(namespaceURI,qualifiedName){
41612                 var node = new Attr();
41613                 var pl = qualifiedName.split(':');
41614                 node.ownerDocument = this;
41615                 node.nodeName = qualifiedName;
41616                 node.name = qualifiedName;
41617                 node.namespaceURI = namespaceURI;
41618                 node.specified = true;
41619                 if(pl.length == 2){
41620                         node.prefix = pl[0];
41621                         node.localName = pl[1];
41622                 }else{
41623                         //el.prefix = null;
41624                         node.localName = qualifiedName;
41625                 }
41626                 return node;
41627         }
41628 };
41629 _extends(Document,Node);
41630
41631
41632 function Element() {
41633         this._nsMap = {};
41634 }
41635 Element.prototype = {
41636         nodeType : ELEMENT_NODE,
41637         hasAttribute : function(name){
41638                 return this.getAttributeNode(name)!=null;
41639         },
41640         getAttribute : function(name){
41641                 var attr = this.getAttributeNode(name);
41642                 return attr && attr.value || '';
41643         },
41644         getAttributeNode : function(name){
41645                 return this.attributes.getNamedItem(name);
41646         },
41647         setAttribute : function(name, value){
41648                 var attr = this.ownerDocument.createAttribute(name);
41649                 attr.value = attr.nodeValue = "" + value;
41650                 this.setAttributeNode(attr);
41651         },
41652         removeAttribute : function(name){
41653                 var attr = this.getAttributeNode(name);
41654                 attr && this.removeAttributeNode(attr);
41655         },
41656         
41657         //four real opeartion method
41658         appendChild:function(newChild){
41659                 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41660                         return this.insertBefore(newChild,null);
41661                 }else{
41662                         return _appendSingleChild(this,newChild);
41663                 }
41664         },
41665         setAttributeNode : function(newAttr){
41666                 return this.attributes.setNamedItem(newAttr);
41667         },
41668         setAttributeNodeNS : function(newAttr){
41669                 return this.attributes.setNamedItemNS(newAttr);
41670         },
41671         removeAttributeNode : function(oldAttr){
41672                 return this.attributes.removeNamedItem(oldAttr.nodeName);
41673         },
41674         //get real attribute name,and remove it by removeAttributeNode
41675         removeAttributeNS : function(namespaceURI, localName){
41676                 var old = this.getAttributeNodeNS(namespaceURI, localName);
41677                 old && this.removeAttributeNode(old);
41678         },
41679         
41680         hasAttributeNS : function(namespaceURI, localName){
41681                 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41682         },
41683         getAttributeNS : function(namespaceURI, localName){
41684                 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41685                 return attr && attr.value || '';
41686         },
41687         setAttributeNS : function(namespaceURI, qualifiedName, value){
41688                 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41689                 attr.value = attr.nodeValue = "" + value;
41690                 this.setAttributeNode(attr);
41691         },
41692         getAttributeNodeNS : function(namespaceURI, localName){
41693                 return this.attributes.getNamedItemNS(namespaceURI, localName);
41694         },
41695         
41696         getElementsByTagName : function(tagName){
41697                 return new LiveNodeList(this,function(base){
41698                         var ls = [];
41699                         _visitNode(base,function(node){
41700                                 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41701                                         ls.push(node);
41702                                 }
41703                         });
41704                         return ls;
41705                 });
41706         },
41707         getElementsByTagNameNS : function(namespaceURI, localName){
41708                 return new LiveNodeList(this,function(base){
41709                         var ls = [];
41710                         _visitNode(base,function(node){
41711                                 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41712                                         ls.push(node);
41713                                 }
41714                         });
41715                         return ls;
41716                 });
41717         }
41718 };
41719 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41720 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41721
41722
41723 _extends(Element,Node);
41724 function Attr() {
41725 }
41726 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41727 _extends(Attr,Node);
41728
41729
41730 function CharacterData() {
41731 }
41732 CharacterData.prototype = {
41733         data : '',
41734         substringData : function(offset, count) {
41735                 return this.data.substring(offset, offset+count);
41736         },
41737         appendData: function(text) {
41738                 text = this.data+text;
41739                 this.nodeValue = this.data = text;
41740                 this.length = text.length;
41741         },
41742         insertData: function(offset,text) {
41743                 this.replaceData(offset,0,text);
41744         
41745         },
41746         appendChild:function(newChild){
41747                 //if(!(newChild instanceof CharacterData)){
41748                         throw new Error(ExceptionMessage[3])
41749                 //}
41750                 return Node.prototype.appendChild.apply(this,arguments)
41751         },
41752         deleteData: function(offset, count) {
41753                 this.replaceData(offset,count,"");
41754         },
41755         replaceData: function(offset, count, text) {
41756                 var start = this.data.substring(0,offset);
41757                 var end = this.data.substring(offset+count);
41758                 text = start + text + end;
41759                 this.nodeValue = this.data = text;
41760                 this.length = text.length;
41761         }
41762 };
41763 _extends(CharacterData,Node);
41764 function Text() {
41765 }
41766 Text.prototype = {
41767         nodeName : "#text",
41768         nodeType : TEXT_NODE,
41769         splitText : function(offset) {
41770                 var text = this.data;
41771                 var newText = text.substring(offset);
41772                 text = text.substring(0, offset);
41773                 this.data = this.nodeValue = text;
41774                 this.length = text.length;
41775                 var newNode = this.ownerDocument.createTextNode(newText);
41776                 if(this.parentNode){
41777                         this.parentNode.insertBefore(newNode, this.nextSibling);
41778                 }
41779                 return newNode;
41780         }
41781 };
41782 _extends(Text,CharacterData);
41783 function Comment() {
41784 }
41785 Comment.prototype = {
41786         nodeName : "#comment",
41787         nodeType : COMMENT_NODE
41788 };
41789 _extends(Comment,CharacterData);
41790
41791 function CDATASection() {
41792 }
41793 CDATASection.prototype = {
41794         nodeName : "#cdata-section",
41795         nodeType : CDATA_SECTION_NODE
41796 };
41797 _extends(CDATASection,CharacterData);
41798
41799
41800 function DocumentType() {
41801 }
41802 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41803 _extends(DocumentType,Node);
41804
41805 function Notation() {
41806 }
41807 Notation.prototype.nodeType = NOTATION_NODE;
41808 _extends(Notation,Node);
41809
41810 function Entity() {
41811 }
41812 Entity.prototype.nodeType = ENTITY_NODE;
41813 _extends(Entity,Node);
41814
41815 function EntityReference() {
41816 }
41817 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41818 _extends(EntityReference,Node);
41819
41820 function DocumentFragment() {
41821 }
41822 DocumentFragment.prototype.nodeName =   "#document-fragment";
41823 DocumentFragment.prototype.nodeType =   DOCUMENT_FRAGMENT_NODE;
41824 _extends(DocumentFragment,Node);
41825
41826
41827 function ProcessingInstruction() {
41828 }
41829 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41830 _extends(ProcessingInstruction,Node);
41831 function XMLSerializer(){}
41832 XMLSerializer.prototype.serializeToString = function(node,attributeSorter){
41833         return node.toString(attributeSorter);
41834 };
41835 Node.prototype.toString =function(attributeSorter){
41836         var buf = [];
41837         serializeToString(this,buf,attributeSorter);
41838         return buf.join('');
41839 };
41840 function serializeToString(node,buf,attributeSorter,isHTML){
41841         switch(node.nodeType){
41842         case ELEMENT_NODE:
41843                 var attrs = node.attributes;
41844                 var len = attrs.length;
41845                 var child = node.firstChild;
41846                 var nodeName = node.tagName;
41847                 isHTML =  (htmlns === node.namespaceURI) ||isHTML; 
41848                 buf.push('<',nodeName);
41849                 if(attributeSorter){
41850                         buf.sort.apply(attrs, attributeSorter);
41851                 }
41852                 for(var i=0;i<len;i++){
41853                         serializeToString(attrs.item(i),buf,attributeSorter,isHTML);
41854                 }
41855                 if(child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)){
41856                         buf.push('>');
41857                         //if is cdata child node
41858                         if(isHTML && /^script$/i.test(nodeName)){
41859                                 if(child){
41860                                         buf.push(child.data);
41861                                 }
41862                         }else{
41863                                 while(child){
41864                                         serializeToString(child,buf,attributeSorter,isHTML);
41865                                         child = child.nextSibling;
41866                                 }
41867                         }
41868                         buf.push('</',nodeName,'>');
41869                 }else{
41870                         buf.push('/>');
41871                 }
41872                 return;
41873         case DOCUMENT_NODE:
41874         case DOCUMENT_FRAGMENT_NODE:
41875                 var child = node.firstChild;
41876                 while(child){
41877                         serializeToString(child,buf,attributeSorter,isHTML);
41878                         child = child.nextSibling;
41879                 }
41880                 return;
41881         case ATTRIBUTE_NODE:
41882                 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
41883         case TEXT_NODE:
41884                 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
41885         case CDATA_SECTION_NODE:
41886                 return buf.push( '<![CDATA[',node.data,']]>');
41887         case COMMENT_NODE:
41888                 return buf.push( "<!--",node.data,"-->");
41889         case DOCUMENT_TYPE_NODE:
41890                 var pubid = node.publicId;
41891                 var sysid = node.systemId;
41892                 buf.push('<!DOCTYPE ',node.name);
41893                 if(pubid){
41894                         buf.push(' PUBLIC "',pubid);
41895                         if (sysid && sysid!='.') {
41896                                 buf.push( '" "',sysid);
41897                         }
41898                         buf.push('">');
41899                 }else if(sysid && sysid!='.'){
41900                         buf.push(' SYSTEM "',sysid,'">');
41901                 }else{
41902                         var sub = node.internalSubset;
41903                         if(sub){
41904                                 buf.push(" [",sub,"]");
41905                         }
41906                         buf.push(">");
41907                 }
41908                 return;
41909         case PROCESSING_INSTRUCTION_NODE:
41910                 return buf.push( "<?",node.target," ",node.data,"?>");
41911         case ENTITY_REFERENCE_NODE:
41912                 return buf.push( '&',node.nodeName,';');
41913         //case ENTITY_NODE:
41914         //case NOTATION_NODE:
41915         default:
41916                 buf.push('??',node.nodeName);
41917         }
41918 }
41919 function importNode(doc,node,deep){
41920         var node2;
41921         switch (node.nodeType) {
41922         case ELEMENT_NODE:
41923                 node2 = node.cloneNode(false);
41924                 node2.ownerDocument = doc;
41925                 //var attrs = node2.attributes;
41926                 //var len = attrs.length;
41927                 //for(var i=0;i<len;i++){
41928                         //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
41929                 //}
41930         case DOCUMENT_FRAGMENT_NODE:
41931                 break;
41932         case ATTRIBUTE_NODE:
41933                 deep = true;
41934                 break;
41935         //case ENTITY_REFERENCE_NODE:
41936         //case PROCESSING_INSTRUCTION_NODE:
41937         ////case TEXT_NODE:
41938         //case CDATA_SECTION_NODE:
41939         //case COMMENT_NODE:
41940         //      deep = false;
41941         //      break;
41942         //case DOCUMENT_NODE:
41943         //case DOCUMENT_TYPE_NODE:
41944         //cannot be imported.
41945         //case ENTITY_NODE:
41946         //case NOTATION_NODE:
41947         //can not hit in level3
41948         //default:throw e;
41949         }
41950         if(!node2){
41951                 node2 = node.cloneNode(false);//false
41952         }
41953         node2.ownerDocument = doc;
41954         node2.parentNode = null;
41955         if(deep){
41956                 var child = node.firstChild;
41957                 while(child){
41958                         node2.appendChild(importNode(doc,child,deep));
41959                         child = child.nextSibling;
41960                 }
41961         }
41962         return node2;
41963 }
41964 //
41965 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
41966 //                                      attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
41967 function cloneNode(doc,node,deep){
41968         var node2 = new node.constructor();
41969         for(var n in node){
41970                 var v = node[n];
41971                 if(typeof v != 'object' ){
41972                         if(v != node2[n]){
41973                                 node2[n] = v;
41974                         }
41975                 }
41976         }
41977         if(node.childNodes){
41978                 node2.childNodes = new NodeList();
41979         }
41980         node2.ownerDocument = doc;
41981         switch (node2.nodeType) {
41982         case ELEMENT_NODE:
41983                 var attrs       = node.attributes;
41984                 var attrs2      = node2.attributes = new NamedNodeMap();
41985                 var len = attrs.length;
41986                 attrs2._ownerElement = node2;
41987                 for(var i=0;i<len;i++){
41988                         node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
41989                 }
41990                 break;;
41991         case ATTRIBUTE_NODE:
41992                 deep = true;
41993         }
41994         if(deep){
41995                 var child = node.firstChild;
41996                 while(child){
41997                         node2.appendChild(cloneNode(doc,child,deep));
41998                         child = child.nextSibling;
41999                 }
42000         }
42001         return node2;
42002 }
42003
42004 function __set__(object,key,value){
42005         object[key] = value;
42006 }
42007 //do dynamic
42008 try{
42009         if(Object.defineProperty){
42010                 Object.defineProperty(LiveNodeList.prototype,'length',{
42011                         get:function(){
42012                                 _updateLiveList(this);
42013                                 return this.$$length;
42014                         }
42015                 });
42016                 Object.defineProperty(Node.prototype,'textContent',{
42017                         get:function(){
42018                                 return getTextContent(this);
42019                         },
42020                         set:function(data){
42021                                 switch(this.nodeType){
42022                                 case 1:
42023                                 case 11:
42024                                         while(this.firstChild){
42025                                                 this.removeChild(this.firstChild);
42026                                         }
42027                                         if(data || String(data)){
42028                                                 this.appendChild(this.ownerDocument.createTextNode(data));
42029                                         }
42030                                         break;
42031                                 default:
42032                                         //TODO:
42033                                         this.data = data;
42034                                         this.value = value;
42035                                         this.nodeValue = data;
42036                                 }
42037                         }
42038                 });
42039                 
42040                 function getTextContent(node){
42041                         switch(node.nodeType){
42042                         case 1:
42043                         case 11:
42044                                 var buf = [];
42045                                 node = node.firstChild;
42046                                 while(node){
42047                                         if(node.nodeType!==7 && node.nodeType !==8){
42048                                                 buf.push(getTextContent(node));
42049                                         }
42050                                         node = node.nextSibling;
42051                                 }
42052                                 return buf.join('');
42053                         default:
42054                                 return node.nodeValue;
42055                         }
42056                 }
42057                 __set__ = function(object,key,value){
42058                         //console.log(value)
42059                         object['$$'+key] = value;
42060                 };
42061         }
42062 }catch(e){//ie8
42063 }
42064
42065 if(typeof commonjsRequire == 'function'){
42066         exports.DOMImplementation = DOMImplementation;
42067         exports.XMLSerializer = XMLSerializer;
42068 }
42069 });
42070
42071 var domParser = createCommonjsModule(function (module, exports) {
42072 function DOMParser(options){
42073         this.options = options ||{locator:{}};
42074         
42075 }
42076 DOMParser.prototype.parseFromString = function(source,mimeType){        
42077         var options = this.options;
42078         var sax$$1 =  new XMLReader();
42079         var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
42080         var errorHandler = options.errorHandler;
42081         var locator = options.locator;
42082         var defaultNSMap = options.xmlns||{};
42083         var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
42084         if(locator){
42085                 domBuilder.setDocumentLocator(locator);
42086         }
42087         
42088         sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
42089         sax$$1.domBuilder = options.domBuilder || domBuilder;
42090         if(/\/x?html?$/.test(mimeType)){
42091                 entityMap.nbsp = '\xa0';
42092                 entityMap.copy = '\xa9';
42093                 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
42094         }
42095         defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
42096         if(source){
42097                 sax$$1.parse(source,defaultNSMap,entityMap);
42098         }else{
42099                 sax$$1.errorHandler.error("invalid document source");
42100         }
42101         return domBuilder.document;
42102 };
42103 function buildErrorHandler(errorImpl,domBuilder,locator){
42104         if(!errorImpl){
42105                 if(domBuilder instanceof DOMHandler){
42106                         return domBuilder;
42107                 }
42108                 errorImpl = domBuilder ;
42109         }
42110         var errorHandler = {};
42111         var isCallback = errorImpl instanceof Function;
42112         locator = locator||{};
42113         function build(key){
42114                 var fn = errorImpl[key];
42115                 if(!fn && isCallback){
42116                         fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
42117                 }
42118                 errorHandler[key] = fn && function(msg){
42119                         fn('[xmldom '+key+']\t'+msg+_locator(locator));
42120                 }||function(){};
42121         }
42122         build('warning');
42123         build('error');
42124         build('fatalError');
42125         return errorHandler;
42126 }
42127
42128 //console.log('#\n\n\n\n\n\n\n####')
42129 /**
42130  * +ContentHandler+ErrorHandler
42131  * +LexicalHandler+EntityResolver2
42132  * -DeclHandler-DTDHandler 
42133  * 
42134  * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
42135  * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
42136  * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
42137  */
42138 function DOMHandler() {
42139     this.cdata = false;
42140 }
42141 function position(locator,node){
42142         node.lineNumber = locator.lineNumber;
42143         node.columnNumber = locator.columnNumber;
42144 }
42145 /**
42146  * @see org.xml.sax.ContentHandler#startDocument
42147  * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
42148  */ 
42149 DOMHandler.prototype = {
42150         startDocument : function() {
42151         this.document = new DOMImplementation().createDocument(null, null, null);
42152         if (this.locator) {
42153                 this.document.documentURI = this.locator.systemId;
42154         }
42155         },
42156         startElement:function(namespaceURI, localName, qName, attrs) {
42157                 var doc = this.document;
42158             var el = doc.createElementNS(namespaceURI, qName||localName);
42159             var len = attrs.length;
42160             appendElement(this, el);
42161             this.currentElement = el;
42162             
42163                 this.locator && position(this.locator,el);
42164             for (var i = 0 ; i < len; i++) {
42165                 var namespaceURI = attrs.getURI(i);
42166                 var value = attrs.getValue(i);
42167                 var qName = attrs.getQName(i);
42168                         var attr = doc.createAttributeNS(namespaceURI, qName);
42169                         if( attr.getOffset){
42170                                 position(attr.getOffset(1),attr);
42171                         }
42172                         attr.value = attr.nodeValue = value;
42173                         el.setAttributeNode(attr);
42174             }
42175         },
42176         endElement:function(namespaceURI, localName, qName) {
42177                 var current = this.currentElement;
42178             var tagName = current.tagName;
42179             this.currentElement = current.parentNode;
42180         },
42181         startPrefixMapping:function(prefix, uri) {
42182         },
42183         endPrefixMapping:function(prefix) {
42184         },
42185         processingInstruction:function(target, data) {
42186             var ins = this.document.createProcessingInstruction(target, data);
42187             this.locator && position(this.locator,ins);
42188             appendElement(this, ins);
42189         },
42190         ignorableWhitespace:function(ch, start, length) {
42191         },
42192         characters:function(chars, start, length) {
42193                 chars = _toString.apply(this,arguments);
42194                 //console.log(chars)
42195                 if(this.currentElement && chars){
42196                         if (this.cdata) {
42197                                 var charNode = this.document.createCDATASection(chars);
42198                                 this.currentElement.appendChild(charNode);
42199                         } else {
42200                                 var charNode = this.document.createTextNode(chars);
42201                                 this.currentElement.appendChild(charNode);
42202                         }
42203                         this.locator && position(this.locator,charNode);
42204                 }
42205         },
42206         skippedEntity:function(name) {
42207         },
42208         endDocument:function() {
42209                 this.document.normalize();
42210         },
42211         setDocumentLocator:function (locator) {
42212             if(this.locator = locator){// && !('lineNumber' in locator)){
42213                 locator.lineNumber = 0;
42214             }
42215         },
42216         //LexicalHandler
42217         comment:function(chars, start, length) {
42218                 chars = _toString.apply(this,arguments);
42219             var comm = this.document.createComment(chars);
42220             this.locator && position(this.locator,comm);
42221             appendElement(this, comm);
42222         },
42223         
42224         startCDATA:function() {
42225             //used in characters() methods
42226             this.cdata = true;
42227         },
42228         endCDATA:function() {
42229             this.cdata = false;
42230         },
42231         
42232         startDTD:function(name, publicId, systemId) {
42233                 var impl = this.document.implementation;
42234             if (impl && impl.createDocumentType) {
42235                 var dt = impl.createDocumentType(name, publicId, systemId);
42236                 this.locator && position(this.locator,dt);
42237                 appendElement(this, dt);
42238             }
42239         },
42240         /**
42241          * @see org.xml.sax.ErrorHandler
42242          * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
42243          */
42244         warning:function(error) {
42245                 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
42246         },
42247         error:function(error) {
42248                 console.error('[xmldom error]\t'+error,_locator(this.locator));
42249         },
42250         fatalError:function(error) {
42251                 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
42252             throw error;
42253         }
42254 };
42255 function _locator(l){
42256         if(l){
42257                 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
42258         }
42259 }
42260 function _toString(chars,start,length){
42261         if(typeof chars == 'string'){
42262                 return chars.substr(start,length)
42263         }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
42264                 if(chars.length >= start+length || start){
42265                         return new java.lang.String(chars,start,length)+'';
42266                 }
42267                 return chars;
42268         }
42269 }
42270
42271 /*
42272  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
42273  * used method of org.xml.sax.ext.LexicalHandler:
42274  *  #comment(chars, start, length)
42275  *  #startCDATA()
42276  *  #endCDATA()
42277  *  #startDTD(name, publicId, systemId)
42278  *
42279  *
42280  * IGNORED method of org.xml.sax.ext.LexicalHandler:
42281  *  #endDTD()
42282  *  #startEntity(name)
42283  *  #endEntity(name)
42284  *
42285  *
42286  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
42287  * IGNORED method of org.xml.sax.ext.DeclHandler
42288  *      #attributeDecl(eName, aName, type, mode, value)
42289  *  #elementDecl(name, model)
42290  *  #externalEntityDecl(name, publicId, systemId)
42291  *  #internalEntityDecl(name, value)
42292  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
42293  * IGNORED method of org.xml.sax.EntityResolver2
42294  *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
42295  *  #resolveEntity(publicId, systemId)
42296  *  #getExternalSubset(name, baseURI)
42297  * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
42298  * IGNORED method of org.xml.sax.DTDHandler
42299  *  #notationDecl(name, publicId, systemId) {};
42300  *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
42301  */
42302 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
42303         DOMHandler.prototype[key] = function(){return null};
42304 });
42305
42306 /* 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 */
42307 function appendElement (hander,node) {
42308     if (!hander.currentElement) {
42309         hander.document.appendChild(node);
42310     } else {
42311         hander.currentElement.appendChild(node);
42312     }
42313 }//appendChild and setAttributeNS are preformance key
42314
42315 if(typeof commonjsRequire == 'function'){
42316         var XMLReader = sax.XMLReader;
42317         var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
42318         exports.XMLSerializer = dom.XMLSerializer ;
42319         exports.DOMParser = DOMParser;
42320 }
42321 });
42322
42323 var togeojson = createCommonjsModule(function (module, exports) {
42324 var toGeoJSON = (function() {
42325     'use strict';
42326
42327     var removeSpace = /\s*/g,
42328         trimSpace = /^\s*|\s*$/g,
42329         splitSpace = /\s+/;
42330     // generate a short, numeric hash of a string
42331     function okhash(x) {
42332         if (!x || !x.length) return 0;
42333         for (var i = 0, h = 0; i < x.length; i++) {
42334             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
42335         } return h;
42336     }
42337     // all Y children of X
42338     function get(x, y) { return x.getElementsByTagName(y); }
42339     function attr(x, y) { return x.getAttribute(y); }
42340     function attrf(x, y) { return parseFloat(attr(x, y)); }
42341     // one Y child of X, if any, otherwise null
42342     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
42343     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
42344     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
42345     // cast array x into numbers
42346     function numarray(x) {
42347         for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
42348         return o;
42349     }
42350     // get the content of a text node, if any
42351     function nodeVal(x) {
42352         if (x) { norm(x); }
42353         return (x && x.textContent) || '';
42354     }
42355     // get the contents of multiple text nodes, if present
42356     function getMulti(x, ys) {
42357         var o = {}, n, k;
42358         for (k = 0; k < ys.length; k++) {
42359             n = get1(x, ys[k]);
42360             if (n) o[ys[k]] = nodeVal(n);
42361         }
42362         return o;
42363     }
42364     // add properties of Y to X, overwriting if present in both
42365     function extend(x, y) { for (var k in y) x[k] = y[k]; }
42366     // get one coordinate from a coordinate array, if any
42367     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
42368     // get all coordinates from a coordinate array as [[],[]]
42369     function coord(v) {
42370         var coords = v.replace(trimSpace, '').split(splitSpace),
42371             o = [];
42372         for (var i = 0; i < coords.length; i++) {
42373             o.push(coord1(coords[i]));
42374         }
42375         return o;
42376     }
42377     function coordPair(x) {
42378         var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
42379             ele = get1(x, 'ele'),
42380             // handle namespaced attribute in browser
42381             heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
42382             time = get1(x, 'time'),
42383             e;
42384         if (ele) {
42385             e = parseFloat(nodeVal(ele));
42386             if (!isNaN(e)) {
42387                 ll.push(e);
42388             }
42389         }
42390         return {
42391             coordinates: ll,
42392             time: time ? nodeVal(time) : null,
42393             heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
42394         };
42395     }
42396
42397     // create a new feature collection parent object
42398     function fc() {
42399         return {
42400             type: 'FeatureCollection',
42401             features: []
42402         };
42403     }
42404
42405     var serializer;
42406     if (typeof XMLSerializer !== 'undefined') {
42407         /* istanbul ignore next */
42408         serializer = new XMLSerializer();
42409     // only require xmldom in a node environment
42410     } else if ('object' === 'object' && typeof process === 'object' && !process.browser) {
42411         serializer = new (domParser.XMLSerializer)();
42412     }
42413     function xml2str(str) {
42414         // IE9 will create a new XMLSerializer but it'll crash immediately.
42415         // This line is ignored because we don't run coverage tests in IE9
42416         /* istanbul ignore next */
42417         if (str.xml !== undefined) return str.xml;
42418         return serializer.serializeToString(str);
42419     }
42420
42421     var t = {
42422         kml: function(doc) {
42423
42424             var gj = fc(),
42425                 // styleindex keeps track of hashed styles in order to match features
42426                 styleIndex = {}, styleByHash = {},
42427                 // stylemapindex keeps track of style maps to expose in properties
42428                 styleMapIndex = {},
42429                 // atomic geospatial types supported by KML - MultiGeometry is
42430                 // handled separately
42431                 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
42432                 // all root placemarks in the file
42433                 placemarks = get(doc, 'Placemark'),
42434                 styles = get(doc, 'Style'),
42435                 styleMaps = get(doc, 'StyleMap');
42436
42437             for (var k = 0; k < styles.length; k++) {
42438                 var hash = okhash(xml2str(styles[k])).toString(16);
42439                 styleIndex['#' + attr(styles[k], 'id')] = hash;
42440                 styleByHash[hash] = styles[k];
42441             }
42442             for (var l = 0; l < styleMaps.length; l++) {
42443                 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
42444                 var pairs = get(styleMaps[l], 'Pair');
42445                 var pairsMap = {};
42446                 for (var m = 0; m < pairs.length; m++) {
42447                     pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
42448                 }
42449                 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
42450
42451             }
42452             for (var j = 0; j < placemarks.length; j++) {
42453                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
42454             }
42455             function kmlColor(v) {
42456                 var color, opacity;
42457                 v = v || '';
42458                 if (v.substr(0, 1) === '#') { v = v.substr(1); }
42459                 if (v.length === 6 || v.length === 3) { color = v; }
42460                 if (v.length === 8) {
42461                     opacity = parseInt(v.substr(0, 2), 16) / 255;
42462                     color = '#' + v.substr(6, 2) +
42463                         v.substr(4, 2) +
42464                         v.substr(2, 2);
42465                 }
42466                 return [color, isNaN(opacity) ? undefined : opacity];
42467             }
42468             function gxCoord(v) { return numarray(v.split(' ')); }
42469             function gxCoords(root) {
42470                 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
42471                 if (elems.length === 0) elems = get(root, 'gx:coord');
42472                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
42473                 var timeElems = get(root, 'when');
42474                 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
42475                 return {
42476                     coords: coords,
42477                     times: times
42478                 };
42479             }
42480             function getGeometry(root) {
42481                 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
42482                 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
42483                 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
42484                 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
42485                 for (i = 0; i < geotypes.length; i++) {
42486                     geomNodes = get(root, geotypes[i]);
42487                     if (geomNodes) {
42488                         for (j = 0; j < geomNodes.length; j++) {
42489                             geomNode = geomNodes[j];
42490                             if (geotypes[i] === 'Point') {
42491                                 geoms.push({
42492                                     type: 'Point',
42493                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
42494                                 });
42495                             } else if (geotypes[i] === 'LineString') {
42496                                 geoms.push({
42497                                     type: 'LineString',
42498                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
42499                                 });
42500                             } else if (geotypes[i] === 'Polygon') {
42501                                 var rings = get(geomNode, 'LinearRing'),
42502                                     coords = [];
42503                                 for (k = 0; k < rings.length; k++) {
42504                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
42505                                 }
42506                                 geoms.push({
42507                                     type: 'Polygon',
42508                                     coordinates: coords
42509                                 });
42510                             } else if (geotypes[i] === 'Track' ||
42511                                 geotypes[i] === 'gx:Track') {
42512                                 var track = gxCoords(geomNode);
42513                                 geoms.push({
42514                                     type: 'LineString',
42515                                     coordinates: track.coords
42516                                 });
42517                                 if (track.times.length) coordTimes.push(track.times);
42518                             }
42519                         }
42520                     }
42521                 }
42522                 return {
42523                     geoms: geoms,
42524                     coordTimes: coordTimes
42525                 };
42526             }
42527             function getPlacemark(root) {
42528                 var geomsAndTimes = getGeometry(root), i, properties = {},
42529                     name = nodeVal(get1(root, 'name')),
42530                     address = nodeVal(get1(root, 'address')),
42531                     styleUrl = nodeVal(get1(root, 'styleUrl')),
42532                     description = nodeVal(get1(root, 'description')),
42533                     timeSpan = get1(root, 'TimeSpan'),
42534                     timeStamp = get1(root, 'TimeStamp'),
42535                     extendedData = get1(root, 'ExtendedData'),
42536                     lineStyle = get1(root, 'LineStyle'),
42537                     polyStyle = get1(root, 'PolyStyle'),
42538                     visibility = get1(root, 'visibility');
42539
42540                 if (!geomsAndTimes.geoms.length) return [];
42541                 if (name) properties.name = name;
42542                 if (address) properties.address = address;
42543                 if (styleUrl) {
42544                     if (styleUrl[0] !== '#') {
42545                         styleUrl = '#' + styleUrl;
42546                     }
42547
42548                     properties.styleUrl = styleUrl;
42549                     if (styleIndex[styleUrl]) {
42550                         properties.styleHash = styleIndex[styleUrl];
42551                     }
42552                     if (styleMapIndex[styleUrl]) {
42553                         properties.styleMapHash = styleMapIndex[styleUrl];
42554                         properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42555                     }
42556                     // Try to populate the lineStyle or polyStyle since we got the style hash
42557                     var style = styleByHash[properties.styleHash];
42558                     if (style) {
42559                         if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42560                         if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42561                     }
42562                 }
42563                 if (description) properties.description = description;
42564                 if (timeSpan) {
42565                     var begin = nodeVal(get1(timeSpan, 'begin'));
42566                     var end = nodeVal(get1(timeSpan, 'end'));
42567                     properties.timespan = { begin: begin, end: end };
42568                 }
42569                 if (timeStamp) {
42570                     properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42571                 }
42572                 if (lineStyle) {
42573                     var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42574                         color = linestyles[0],
42575                         opacity = linestyles[1],
42576                         width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42577                     if (color) properties.stroke = color;
42578                     if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42579                     if (!isNaN(width)) properties['stroke-width'] = width;
42580                 }
42581                 if (polyStyle) {
42582                     var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42583                         pcolor = polystyles[0],
42584                         popacity = polystyles[1],
42585                         fill = nodeVal(get1(polyStyle, 'fill')),
42586                         outline = nodeVal(get1(polyStyle, 'outline'));
42587                     if (pcolor) properties.fill = pcolor;
42588                     if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42589                     if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42590                     if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42591                 }
42592                 if (extendedData) {
42593                     var datas = get(extendedData, 'Data'),
42594                         simpleDatas = get(extendedData, 'SimpleData');
42595
42596                     for (i = 0; i < datas.length; i++) {
42597                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42598                     }
42599                     for (i = 0; i < simpleDatas.length; i++) {
42600                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42601                     }
42602                 }
42603                 if (visibility) {
42604                     properties.visibility = nodeVal(visibility);
42605                 }
42606                 if (geomsAndTimes.coordTimes.length) {
42607                     properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42608                         geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42609                 }
42610                 var feature = {
42611                     type: 'Feature',
42612                     geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42613                         type: 'GeometryCollection',
42614                         geometries: geomsAndTimes.geoms
42615                     },
42616                     properties: properties
42617                 };
42618                 if (attr(root, 'id')) feature.id = attr(root, 'id');
42619                 return [feature];
42620             }
42621             return gj;
42622         },
42623         gpx: function(doc) {
42624             var i,
42625                 tracks = get(doc, 'trk'),
42626                 routes = get(doc, 'rte'),
42627                 waypoints = get(doc, 'wpt'),
42628                 // a feature collection
42629                 gj = fc(),
42630                 feature;
42631             for (i = 0; i < tracks.length; i++) {
42632                 feature = getTrack(tracks[i]);
42633                 if (feature) gj.features.push(feature);
42634             }
42635             for (i = 0; i < routes.length; i++) {
42636                 feature = getRoute(routes[i]);
42637                 if (feature) gj.features.push(feature);
42638             }
42639             for (i = 0; i < waypoints.length; i++) {
42640                 gj.features.push(getPoint(waypoints[i]));
42641             }
42642             function getPoints(node, pointname) {
42643                 var pts = get(node, pointname),
42644                     line = [],
42645                     times = [],
42646                     heartRates = [],
42647                     l = pts.length;
42648                 if (l < 2) return {};  // Invalid line in GeoJSON
42649                 for (var i = 0; i < l; i++) {
42650                     var c = coordPair(pts[i]);
42651                     line.push(c.coordinates);
42652                     if (c.time) times.push(c.time);
42653                     if (c.heartRate) heartRates.push(c.heartRate);
42654                 }
42655                 return {
42656                     line: line,
42657                     times: times,
42658                     heartRates: heartRates
42659                 };
42660             }
42661             function getTrack(node) {
42662                 var segments = get(node, 'trkseg'),
42663                     track = [],
42664                     times = [],
42665                     heartRates = [],
42666                     line;
42667                 for (var i = 0; i < segments.length; i++) {
42668                     line = getPoints(segments[i], 'trkpt');
42669                     if (line) {
42670                         if (line.line) track.push(line.line);
42671                         if (line.times && line.times.length) times.push(line.times);
42672                         if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42673                     }
42674                 }
42675                 if (track.length === 0) return;
42676                 var properties = getProperties(node);
42677                 extend(properties, getLineStyle(get1(node, 'extensions')));
42678                 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42679                 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42680                 return {
42681                     type: 'Feature',
42682                     properties: properties,
42683                     geometry: {
42684                         type: track.length === 1 ? 'LineString' : 'MultiLineString',
42685                         coordinates: track.length === 1 ? track[0] : track
42686                     }
42687                 };
42688             }
42689             function getRoute(node) {
42690                 var line = getPoints(node, 'rtept');
42691                 if (!line.line) return;
42692                 var prop = getProperties(node);
42693                 extend(prop, getLineStyle(get1(node, 'extensions')));
42694                 var routeObj = {
42695                     type: 'Feature',
42696                     properties: prop,
42697                     geometry: {
42698                         type: 'LineString',
42699                         coordinates: line.line
42700                     }
42701                 };
42702                 return routeObj;
42703             }
42704             function getPoint(node) {
42705                 var prop = getProperties(node);
42706                 extend(prop, getMulti(node, ['sym']));
42707                 return {
42708                     type: 'Feature',
42709                     properties: prop,
42710                     geometry: {
42711                         type: 'Point',
42712                         coordinates: coordPair(node).coordinates
42713                     }
42714                 };
42715             }
42716             function getLineStyle(extensions) {
42717                 var style = {};
42718                 if (extensions) {
42719                     var lineStyle = get1(extensions, 'line');
42720                     if (lineStyle) {
42721                         var color = nodeVal(get1(lineStyle, 'color')),
42722                             opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))),
42723                             width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42724                         if (color) style.stroke = color;
42725                         if (!isNaN(opacity)) style['stroke-opacity'] = opacity;
42726                         // GPX width is in mm, convert to px with 96 px per inch
42727                         if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4;
42728                     }
42729                 }
42730                 return style;
42731             }
42732             function getProperties(node) {
42733                 var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']),
42734                     links = get(node, 'link');
42735                 if (links.length) prop.links = [];
42736                 for (var i = 0, link; i < links.length; i++) {
42737                     link = { href: attr(links[i], 'href') };
42738                     extend(link, getMulti(links[i], ['text', 'type']));
42739                     prop.links.push(link);
42740                 }
42741                 return prop;
42742             }
42743             return gj;
42744         }
42745     };
42746     return t;
42747 })();
42748
42749 module.exports = toGeoJSON;
42750 });
42751
42752 function svgGpx(projection, context, dispatch$$1) {
42753     var showLabels = true,
42754         detected = utilDetect(),
42755         layer;
42756
42757
42758     function init() {
42759         if (svgGpx.initialized) return;  // run once
42760
42761         svgGpx.geojson = {};
42762         svgGpx.enabled = true;
42763
42764         function over() {
42765             event.stopPropagation();
42766             event.preventDefault();
42767             event.dataTransfer.dropEffect = 'copy';
42768         }
42769
42770         select('body')
42771             .attr('dropzone', 'copy')
42772             .on('drop.localgpx', function() {
42773                 event.stopPropagation();
42774                 event.preventDefault();
42775                 if (!detected.filedrop) return;
42776                 drawGpx.files(event.dataTransfer.files);
42777             })
42778             .on('dragenter.localgpx', over)
42779             .on('dragexit.localgpx', over)
42780             .on('dragover.localgpx', over);
42781
42782         svgGpx.initialized = true;
42783     }
42784
42785
42786     function drawGpx(selection$$1) {
42787         var geojson = svgGpx.geojson,
42788             enabled = svgGpx.enabled;
42789
42790         layer = selection$$1.selectAll('.layer-gpx')
42791             .data(enabled ? [0] : []);
42792
42793         layer.exit()
42794             .remove();
42795
42796         layer = layer.enter()
42797             .append('g')
42798             .attr('class', 'layer-gpx')
42799             .merge(layer);
42800
42801
42802         var paths = layer
42803             .selectAll('path')
42804             .data([geojson]);
42805
42806         paths.exit()
42807             .remove();
42808
42809         paths = paths.enter()
42810             .append('path')
42811             .attr('class', 'gpx')
42812             .merge(paths);
42813
42814
42815         var path$$1 = index$4(projection);
42816
42817         paths
42818             .attr('d', path$$1);
42819
42820
42821         var labels = layer.selectAll('text')
42822             .data(showLabels && geojson.features ? geojson.features : []);
42823
42824         labels.exit()
42825             .remove();
42826
42827         labels = labels.enter()
42828             .append('text')
42829             .attr('class', 'gpx')
42830             .merge(labels);
42831
42832         labels
42833             .text(function(d) {
42834                 return d.properties.desc || d.properties.name;
42835             })
42836             .attr('x', function(d) {
42837                 var centroid = path$$1.centroid(d);
42838                 return centroid[0] + 7;
42839             })
42840             .attr('y', function(d) {
42841                 var centroid = path$$1.centroid(d);
42842                 return centroid[1];
42843             });
42844
42845     }
42846
42847
42848     function toDom(x) {
42849         return (new DOMParser()).parseFromString(x, 'text/xml');
42850     }
42851
42852
42853     function getExtension(fileName) {
42854         if (lodash.isUndefined(fileName)) {
42855             return '';
42856         }
42857
42858         var lastDotIndex = fileName.lastIndexOf('.');
42859         if (lastDotIndex < 0) {
42860             return '';
42861         }
42862
42863         return fileName.substr(lastDotIndex);
42864     }
42865
42866
42867     function parseSaveAndZoom(extension, data) {
42868         switch (extension) {
42869             default:
42870                 drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
42871                 break;
42872             case '.kml':
42873                 drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
42874                 break;
42875             case '.geojson':
42876             case '.json':
42877                 drawGpx.geojson(JSON.parse(data)).fitZoom();
42878                 break;
42879         }
42880     }
42881
42882
42883     drawGpx.showLabels = function(_) {
42884         if (!arguments.length) return showLabels;
42885         showLabels = _;
42886         return this;
42887     };
42888
42889
42890     drawGpx.enabled = function(_) {
42891         if (!arguments.length) return svgGpx.enabled;
42892         svgGpx.enabled = _;
42893         dispatch$$1.call('change');
42894         return this;
42895     };
42896
42897
42898     drawGpx.hasGpx = function() {
42899         var geojson = svgGpx.geojson;
42900         return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42901     };
42902
42903
42904     drawGpx.geojson = function(gj) {
42905         if (!arguments.length) return svgGpx.geojson;
42906         if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42907         svgGpx.geojson = gj;
42908         dispatch$$1.call('change');
42909         return this;
42910     };
42911
42912
42913     drawGpx.url = function(url) {
42914         text(url, function(err, data) {
42915             if (!err) {
42916                 var extension = getExtension(url);
42917                 parseSaveAndZoom(extension, data);
42918             }
42919         });
42920         return this;
42921     };
42922
42923
42924     drawGpx.files = function(fileList) {
42925         if (!fileList.length) return this;
42926         var f = fileList[0],
42927             reader = new FileReader();
42928
42929         reader.onload = (function(file) {
42930             var extension = getExtension(file.name);
42931
42932             return function (e) {
42933                 parseSaveAndZoom(extension, e.target.result);
42934             };
42935         })(f);
42936
42937         reader.readAsText(f);
42938         return this;
42939     };
42940
42941
42942     drawGpx.fitZoom = function() {
42943         if (!this.hasGpx()) return this;
42944         var geojson = svgGpx.geojson;
42945
42946         var map$$1 = context.map(),
42947             viewport = map$$1.trimmedExtent().polygon(),
42948             coords = lodash.reduce(geojson.features, function(coords, feature) {
42949                 var c = feature.geometry.coordinates;
42950
42951                 /* eslint-disable no-fallthrough */
42952                 switch (feature.geometry.type) {
42953                     case 'Point':
42954                         c = [c];
42955                     case 'MultiPoint':
42956                     case 'LineString':
42957                         break;
42958
42959                     case 'MultiPolygon':
42960                         c = lodash.flatten(c);
42961                     case 'Polygon':
42962                     case 'MultiLineString':
42963                         c = lodash.flatten(c);
42964                         break;
42965                 }
42966                 /* eslint-enable no-fallthrough */
42967
42968                 return lodash.union(coords, c);
42969             }, []);
42970
42971         if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42972             var extent$$1 = geoExtent$$1(bounds({ type: 'LineString', coordinates: coords }));
42973             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
42974         }
42975
42976         return this;
42977     };
42978
42979
42980     init();
42981     return drawGpx;
42982 }
42983
42984 function svgIcon(name, svgklass, useklass) {
42985     return function drawIcon(selection) {
42986         selection.selectAll('svg')
42987             .data([0])
42988             .enter()
42989             .append('svg')
42990             .attr('class', 'icon ' + (svgklass || ''))
42991             .append('use')
42992             .attr('xlink:href', name)
42993             .attr('class', useklass);
42994     };
42995 }
42996
42997 function svgLabels(projection, context) {
42998     var path$$1 = index$4(projection),
42999         detected = utilDetect(),
43000         baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
43001         rdrawn = index$9(),
43002         rskipped = index$9(),
43003         textWidthCache = {},
43004         entitybboxes = {};
43005
43006     // Listed from highest to lowest priority
43007     var labelStack = [
43008         ['line', 'aeroway', '*', 12],
43009         ['line', 'highway', 'motorway', 12],
43010         ['line', 'highway', 'trunk', 12],
43011         ['line', 'highway', 'primary', 12],
43012         ['line', 'highway', 'secondary', 12],
43013         ['line', 'highway', 'tertiary', 12],
43014         ['line', 'highway', '*', 12],
43015         ['line', 'railway', '*', 12],
43016         ['line', 'waterway', '*', 12],
43017         ['area', 'aeroway', '*', 12],
43018         ['area', 'amenity', '*', 12],
43019         ['area', 'building', '*', 12],
43020         ['area', 'historic', '*', 12],
43021         ['area', 'leisure', '*', 12],
43022         ['area', 'man_made', '*', 12],
43023         ['area', 'natural', '*', 12],
43024         ['area', 'shop', '*', 12],
43025         ['area', 'tourism', '*', 12],
43026         ['area', 'camp_site', '*', 12],
43027         ['point', 'aeroway', '*', 10],
43028         ['point', 'amenity', '*', 10],
43029         ['point', 'building', '*', 10],
43030         ['point', 'historic', '*', 10],
43031         ['point', 'leisure', '*', 10],
43032         ['point', 'man_made', '*', 10],
43033         ['point', 'natural', '*', 10],
43034         ['point', 'shop', '*', 10],
43035         ['point', 'tourism', '*', 10],
43036         ['point', 'camp_site', '*', 10],
43037         ['line', 'name', '*', 12],
43038         ['area', 'name', '*', 12],
43039         ['point', 'name', '*', 10]
43040     ];
43041
43042
43043     function blacklisted(preset) {
43044         var noIcons = ['building', 'landuse', 'natural'];
43045         return lodash.some(noIcons, function(s) {
43046             return preset.id.indexOf(s) >= 0;
43047         });
43048     }
43049
43050
43051     function get(array, prop) {
43052         return function(d, i) { return array[i][prop]; };
43053     }
43054
43055
43056     function textWidth(text$$1, size, elem) {
43057         var c = textWidthCache[size];
43058         if (!c) c = textWidthCache[size] = {};
43059
43060         if (c[text$$1]) {
43061             return c[text$$1];
43062
43063         } else if (elem) {
43064             c[text$$1] = elem.getComputedTextLength();
43065             return c[text$$1];
43066
43067         } else {
43068             var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43069             if (str === null) {
43070                 return size / 3 * 2 * text$$1.length;
43071             } else {
43072                 return size / 3 * (2 * text$$1.length + str.length);
43073             }
43074         }
43075     }
43076
43077
43078     function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43079         var paths = selection$$1.selectAll('path')
43080             .filter(filter)
43081             .data(entities, osmEntity$$1.key);
43082
43083         paths.exit()
43084             .remove();
43085
43086         paths.enter()
43087             .append('path')
43088             .style('stroke-width', get(labels, 'font-size'))
43089             .attr('id', function(d) { return 'labelpath-' + d.id; })
43090             .attr('class', classes)
43091             .merge(paths)
43092             .attr('d', get(labels, 'lineString'));
43093     }
43094
43095
43096     function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43097         var texts = selection$$1.selectAll('text.' + classes)
43098             .filter(filter)
43099             .data(entities, osmEntity$$1.key);
43100
43101         texts.exit()
43102             .remove();
43103
43104         texts.enter()
43105             .append('text')
43106             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43107             .attr('dy', baselineHack ? '0.35em' : null)
43108             .append('textPath')
43109             .attr('class', 'textpath');
43110
43111         texts = selection$$1.selectAll('text.' + classes);
43112
43113         texts.selectAll('.textpath')
43114             .filter(filter)
43115             .data(entities, osmEntity$$1.key)
43116             .attr('startOffset', '50%')
43117             .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43118             .text(utilDisplayNameForPath);
43119     }
43120
43121
43122     function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43123         var texts = selection$$1.selectAll('text.' + classes)
43124             .filter(filter)
43125             .data(entities, osmEntity$$1.key);
43126
43127         texts.exit()
43128             .remove();
43129
43130         texts = texts.enter()
43131             .append('text')
43132             .attr('class', function(d, i) {
43133                 return classes + ' ' + labels[i].classes + ' ' + d.id;
43134             })
43135             .merge(texts);
43136
43137         texts
43138             .attr('x', get(labels, 'x'))
43139             .attr('y', get(labels, 'y'))
43140             .style('text-anchor', get(labels, 'textAnchor'))
43141             .text(utilDisplayName)
43142             .each(function(d, i) {
43143                 textWidth(utilDisplayName(d), labels[i].height, this);
43144             });
43145     }
43146
43147
43148     function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43149         entities = entities.filter(hasText);
43150         labels = labels.filter(hasText);
43151         drawPointLabels(selection$$1, entities, filter, classes, labels);
43152
43153         function hasText(d, i) {
43154             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43155         }
43156     }
43157
43158
43159     function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43160         var icons = selection$$1.selectAll('use.' + classes)
43161             .filter(filter)
43162             .data(entities, osmEntity$$1.key);
43163
43164         icons.exit()
43165             .remove();
43166
43167         icons = icons.enter()
43168             .append('use')
43169             .attr('class', 'icon ' + classes)
43170             .attr('width', '17px')
43171             .attr('height', '17px')
43172             .merge(icons);
43173
43174         icons
43175             .attr('transform', get(labels, 'transform'))
43176             .attr('xlink:href', function(d) {
43177                 var icon = context.presets().match(d, context.graph()).icon;
43178                 return '#' + icon + '-15';
43179             });
43180     }
43181
43182
43183     function drawCollisionBoxes(selection$$1, rtree, which) {
43184         var showDebug = context.getDebug('collision'),
43185             classes = 'debug ' + which + ' ' +
43186                 (which === 'debug-skipped' ? 'orange' : 'yellow');
43187
43188         var debug = selection$$1.selectAll('.layer-label-debug')
43189                 .data(showDebug ? [true] : []);
43190
43191         debug.exit()
43192             .remove();
43193
43194         debug = debug.enter()
43195             .append('g')
43196             .attr('class', 'layer-label-debug')
43197             .merge(debug);
43198
43199         if (showDebug) {
43200             var gj = rtree.all().map(function(d) {
43201                 return { type: 'Polygon', coordinates: [[
43202                     [d.minX, d.minY],
43203                     [d.maxX, d.minY],
43204                     [d.maxX, d.maxY],
43205                     [d.minX, d.maxY],
43206                     [d.minX, d.minY]
43207                 ]]};
43208             });
43209
43210             var debugboxes = debug.selectAll('.' + which)
43211                 .data(gj);
43212
43213             debugboxes.exit()
43214                 .remove();
43215
43216             debugboxes = debugboxes.enter()
43217                 .append('path')
43218                 .attr('class', classes)
43219                 .merge(debugboxes);
43220
43221             debugboxes
43222                 .attr('d', index$4());
43223         }
43224     }
43225
43226
43227     function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43228         var lowZoom = context.surface().classed('low-zoom');
43229
43230         var labelable = [], i, j, k, entity, geometry;
43231         for (i = 0; i < labelStack.length; i++) {
43232             labelable.push([]);
43233         }
43234
43235         if (fullRedraw) {
43236             rdrawn.clear();
43237             rskipped.clear();
43238             entitybboxes = {};
43239         } else {
43240             for (i = 0; i < entities.length; i++) {
43241                 entity = entities[i];
43242                 var toRemove = []
43243                     .concat(entitybboxes[entity.id] || [])
43244                     .concat(entitybboxes[entity.id + 'I'] || []);
43245
43246                 for (j = 0; j < toRemove.length; j++) {
43247                     rdrawn.remove(toRemove[j]);
43248                     rskipped.remove(toRemove[j]);
43249                 }
43250             }
43251         }
43252
43253         // Split entities into groups specified by labelStack
43254         for (i = 0; i < entities.length; i++) {
43255             entity = entities[i];
43256             geometry = entity.geometry(graph);
43257             if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43258
43259             var preset = geometry === 'area' && context.presets().match(entity, graph),
43260                 icon = preset && !blacklisted(preset) && preset.icon;
43261
43262             if (!icon && !utilDisplayName(entity))
43263                 continue;
43264
43265             for (k = 0; k < labelStack.length; k++) {
43266                 var matchGeom = labelStack[k][0],
43267                     matchKey = labelStack[k][1],
43268                     matchVal = labelStack[k][2],
43269                     hasVal = entity.tags[matchKey];
43270
43271                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43272                     labelable[k].push(entity);
43273                     break;
43274                 }
43275             }
43276         }
43277
43278         var positions = {
43279             point: [],
43280             line: [],
43281             area: []
43282         };
43283
43284         var labelled = {
43285             point: [],
43286             line: [],
43287             area: []
43288         };
43289
43290         // Try and find a valid label for labellable entities
43291         for (k = 0; k < labelable.length; k++) {
43292             var fontSize = labelStack[k][3];
43293             for (i = 0; i < labelable[k].length; i++) {
43294                 entity = labelable[k][i];
43295                 geometry = entity.geometry(graph);
43296
43297                 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43298                     name = getName(entity),
43299                     width = name && textWidth(name, fontSize),
43300                     p;
43301
43302                 if (geometry === 'point') {
43303                     p = getPointLabel(entity, width, fontSize, geometry);
43304                 } else if (geometry === 'vertex' && !lowZoom) {
43305                     // don't label vertices at low zoom because they don't have icons
43306                     p = getPointLabel(entity, width, fontSize, geometry);
43307                 } else if (geometry === 'line') {
43308                     p = getLineLabel(entity, width, fontSize);
43309                 } else if (geometry === 'area') {
43310                     p = getAreaLabel(entity, width, fontSize);
43311                 }
43312
43313                 if (p) {
43314                     if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43315                     p.classes = geometry + ' tag-' + labelStack[k][1];
43316                     positions[geometry].push(p);
43317                     labelled[geometry].push(entity);
43318                 }
43319             }
43320         }
43321
43322
43323         function getPointLabel(entity, width, height, geometry) {
43324             var y = (geometry === 'point' ? -12 : 0),
43325                 pointOffsets = {
43326                     ltr: [15, y, 'start'],
43327                     rtl: [-15, y, 'end']
43328                 };
43329
43330             var coord = projection(entity.loc),
43331                 margin = 2,
43332                 offset = pointOffsets[textDirection],
43333                 p = {
43334                     height: height,
43335                     width: width,
43336                     x: coord[0] + offset[0],
43337                     y: coord[1] + offset[1],
43338                     textAnchor: offset[2]
43339                 },
43340                 bbox;
43341
43342             if (textDirection === 'rtl') {
43343                 bbox = {
43344                     minX: p.x - width - margin,
43345                     minY: p.y - (height / 2) - margin,
43346                     maxX: p.x + margin,
43347                     maxY: p.y + (height / 2) + margin
43348                 };
43349             } else {
43350                 bbox = {
43351                     minX: p.x - margin,
43352                     minY: p.y - (height / 2) - margin,
43353                     maxX: p.x + width + margin,
43354                     maxY: p.y + (height / 2) + margin
43355                 };
43356             }
43357
43358             if (tryInsert([bbox], entity.id, true)) {
43359                 return p;
43360             }
43361         }
43362
43363
43364         function getLineLabel(entity, width, height) {
43365             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43366                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
43367                 length = geoPathLength(nodes);
43368
43369             if (length < width + 20) return;
43370
43371             // % along the line to attempt to place the label
43372             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43373                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43374             var margin = 3;
43375
43376             for (var i = 0; i < lineOffsets.length; i++) {
43377                 var offset = lineOffsets[i],
43378                     middle = offset / 100 * length,
43379                     start = middle - width / 2;
43380
43381                 if (start < 0 || start + width > length) continue;
43382
43383                 // generate subpath and ignore paths that are invalid or don't cross viewport.
43384                 var sub = subpath(nodes, start, start + width);
43385                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43386                     continue;
43387                 }
43388
43389                 var isReverse = reverse(sub);
43390                 if (isReverse) {
43391                     sub = sub.reverse();
43392                 }
43393
43394                 var bboxes = [],
43395                     boxsize = (height + 2) / 2;
43396
43397                 for (var j = 0; j < sub.length - 1; j++) {
43398                     var a = sub[j];
43399                     var b = sub[j + 1];
43400                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43401
43402                     for (var box = 0; box < num; box++) {
43403                         var p = geoInterp(a, b, box / num);
43404                         var x0 = p[0] - boxsize - margin;
43405                         var y0 = p[1] - boxsize - margin;
43406                         var x1 = p[0] + boxsize + margin;
43407                         var y1 = p[1] + boxsize + margin;
43408
43409                         bboxes.push({
43410                             minX: Math.min(x0, x1),
43411                             minY: Math.min(y0, y1),
43412                             maxX: Math.max(x0, x1),
43413                             maxY: Math.max(y0, y1)
43414                         });
43415                     }
43416                 }
43417
43418                 if (tryInsert(bboxes, entity.id, false)) {
43419                     return {
43420                         'font-size': height + 2,
43421                         lineString: lineString(sub),
43422                         startOffset: offset + '%'
43423                     };
43424                 }
43425             }
43426
43427             function reverse(p) {
43428                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43429                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43430             }
43431
43432             function lineString(nodes) {
43433                 return 'M' + nodes.join('L');
43434             }
43435
43436             function subpath(nodes, from, to) {
43437                 var sofar = 0,
43438                     start, end, i0, i1;
43439
43440                 for (var i = 0; i < nodes.length - 1; i++) {
43441                     var a = nodes[i],
43442                         b = nodes[i + 1];
43443                     var current = geoEuclideanDistance(a, b);
43444                     var portion;
43445                     if (!start && sofar + current >= from) {
43446                         portion = (from - sofar) / current;
43447                         start = [
43448                             a[0] + portion * (b[0] - a[0]),
43449                             a[1] + portion * (b[1] - a[1])
43450                         ];
43451                         i0 = i + 1;
43452                     }
43453                     if (!end && sofar + current >= to) {
43454                         portion = (to - sofar) / current;
43455                         end = [
43456                             a[0] + portion * (b[0] - a[0]),
43457                             a[1] + portion * (b[1] - a[1])
43458                         ];
43459                         i1 = i + 1;
43460                     }
43461                     sofar += current;
43462                 }
43463
43464                 var ret = nodes.slice(i0, i1);
43465                 ret.unshift(start);
43466                 ret.push(end);
43467                 return ret;
43468             }
43469         }
43470
43471
43472         function getAreaLabel(entity, width, height) {
43473             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
43474                 extent$$1 = entity.extent(graph),
43475                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
43476
43477             if (isNaN(centroid[0]) || entitywidth < 20) return;
43478
43479             var iconSize = 20,
43480                 iconX = centroid[0] - (iconSize / 2),
43481                 iconY = centroid[1] - (iconSize / 2),
43482                 margin = 2,
43483                 textOffset = iconSize + margin,
43484                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
43485
43486             var bbox = {
43487                 minX: iconX,
43488                 minY: iconY,
43489                 maxX: iconX + iconSize,
43490                 maxY: iconY + iconSize
43491             };
43492
43493             // try to add icon
43494             if (tryInsert([bbox], entity.id + 'I', true)) {
43495                 if (width && entitywidth >= width + 20) {
43496                     var labelX = centroid[0],
43497                         labelY = centroid[1] + textOffset;
43498
43499                     bbox = {
43500                         minX: labelX - (width / 2) - margin,
43501                         minY: labelY - (height / 2) - margin,
43502                         maxX: labelX + (width / 2) + margin,
43503                         maxY: labelY + (height / 2) + margin
43504                     };
43505
43506                     // try to add label
43507                     if (tryInsert([bbox], entity.id, true)) {
43508                         p.x = labelX;
43509                         p.y = labelY;
43510                         p.textAnchor = 'middle';
43511                         p.height = height;
43512                     }
43513                 }
43514
43515                 return p;
43516             }
43517         }
43518
43519
43520         function tryInsert(bboxes, id, saveSkipped) {
43521             var skipped = false,
43522                 bbox;
43523
43524             for (var i = 0; i < bboxes.length; i++) {
43525                 bbox = bboxes[i];
43526                 bbox.id = id;
43527
43528                 // Check that label is visible
43529                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
43530                     skipped = true;
43531                     break;
43532                 }
43533                 if (rdrawn.collides(bbox)) {
43534                     skipped = true;
43535                     break;
43536                 }
43537             }
43538
43539             entitybboxes[id] = bboxes;
43540
43541             if (skipped) {
43542                 if (saveSkipped) {
43543                     rskipped.load(bboxes);
43544                 }
43545             } else {
43546                 rdrawn.load(bboxes);
43547             }
43548
43549             return !skipped;
43550         }
43551
43552
43553         var label = selection$$1.selectAll('.layer-label'),
43554             halo = selection$$1.selectAll('.layer-halo');
43555
43556         // points
43557         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
43558         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
43559
43560         // lines
43561         drawLinePaths(halo, labelled.line, filter, '', positions.line);
43562         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
43563         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
43564
43565         // areas
43566         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
43567         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
43568         drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
43569         drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
43570
43571         // debug
43572         drawCollisionBoxes(label, rskipped, 'debug-skipped');
43573         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
43574
43575         selection$$1.call(filterLabels);
43576     }
43577
43578
43579     function filterLabels(selection$$1) {
43580         var layers = selection$$1
43581             .selectAll('.layer-label, .layer-halo');
43582
43583         layers.selectAll('.proximate')
43584             .classed('proximate', false);
43585
43586         var mouse$$1 = context.mouse(),
43587             graph = context.graph(),
43588             selectedIDs = context.selectedIDs(),
43589             ids = [],
43590             pad, bbox;
43591
43592         // hide labels near the mouse
43593         if (mouse$$1) {
43594             pad = 20;
43595             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43596             ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43597         }
43598
43599         // hide labels along selected ways, or near selected vertices
43600         for (var i = 0; i < selectedIDs.length; i++) {
43601             var entity = graph.hasEntity(selectedIDs[i]);
43602             if (!entity) continue;
43603             var geometry = entity.geometry(graph);
43604
43605             if (geometry === 'line') {
43606                 ids.push(selectedIDs[i]);
43607             } else if (geometry === 'vertex') {
43608                 var point = context.projection(entity.loc);
43609                 pad = 10;
43610                 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43611                 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43612             }
43613         }
43614
43615         layers.selectAll(utilEntitySelector(ids))
43616             .classed('proximate', true);
43617     }
43618
43619
43620     var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43621
43622
43623     drawLabels.observe = function(selection$$1) {
43624         var listener = function() { throttleFilterLabels(selection$$1); };
43625         selection$$1.on('mousemove.hidelabels', listener);
43626         context.on('enter.hidelabels', listener);
43627     };
43628
43629
43630     drawLabels.off = function(selection$$1) {
43631         throttleFilterLabels.cancel();
43632         selection$$1.on('mousemove.hidelabels', null);
43633         context.on('enter.hidelabels', null);
43634     };
43635
43636
43637     return drawLabels;
43638 }
43639
43640 function refresh(selection, node) {
43641     var cr = node.getBoundingClientRect();
43642     var prop = [cr.width, cr.height];
43643     selection.property('__dimensions__', prop);
43644     return prop;
43645 }
43646
43647 function utilGetDimensions(selection, force) {
43648     if (!selection || selection.empty()) {
43649         return [0, 0];
43650     }
43651     var node = selection.node(),
43652         cached = selection.property('__dimensions__');
43653     return (!cached || force) ? refresh(selection, node) : cached;
43654 }
43655
43656
43657 function utilSetDimensions(selection, dimensions) {
43658     if (!selection || selection.empty()) {
43659         return selection;
43660     }
43661     var node = selection.node();
43662     if (dimensions === null) {
43663         refresh(selection, node);
43664         return selection;
43665     }
43666     return selection
43667         .property('__dimensions__', [dimensions[0], dimensions[1]])
43668         .attr('width', dimensions[0])
43669         .attr('height', dimensions[1]);
43670 }
43671
43672 function svgPointTransform(projection) {
43673     return function(entity) {
43674         // http://jsperf.com/short-array-join
43675         var pt = projection(entity.loc);
43676         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43677     };
43678 }
43679
43680 function d3geoTile() {
43681   var size = [960, 500],
43682       scale = 256,
43683       scaleExtent = [0, 20],
43684       translate = [size[0] / 2, size[1] / 2],
43685       zoomDelta = 0;
43686
43687   function bound(_) {
43688       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43689   }
43690
43691   function tile() {
43692     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43693         z0 = bound(Math.round(z + zoomDelta)),
43694         k = Math.pow(2, z - z0 + 8),
43695         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43696         tiles = [],
43697         cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43698         rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43699
43700     rows.forEach(function(y) {
43701       cols.forEach(function(x) {
43702         tiles.push([x, y, z0]);
43703       });
43704     });
43705
43706     tiles.translate = origin;
43707     tiles.scale = k;
43708
43709     return tiles;
43710   }
43711
43712   tile.scaleExtent = function(_) {
43713     if (!arguments.length) return scaleExtent;
43714     scaleExtent = _;
43715     return tile;
43716   };
43717
43718   tile.size = function(_) {
43719     if (!arguments.length) return size;
43720     size = _;
43721     return tile;
43722   };
43723
43724   tile.scale = function(_) {
43725     if (!arguments.length) return scale;
43726     scale = _;
43727     return tile;
43728   };
43729
43730   tile.translate = function(_) {
43731     if (!arguments.length) return translate;
43732     translate = _;
43733     return tile;
43734   };
43735
43736   tile.zoomDelta = function(_) {
43737     if (!arguments.length) return zoomDelta;
43738     zoomDelta = +_;
43739     return tile;
43740   };
43741
43742   return tile;
43743 }
43744
43745 /* global Mapillary:false */
43746 var apibase = 'https://a.mapillary.com/v2/';
43747 var viewercss = 'mapillary-js/mapillary.min.css';
43748 var viewerjs = 'mapillary-js/mapillary.min.js';
43749 var trafficocss = 'traffico/stylesheets/traffico.css';
43750 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43751 var maxResults = 1000;
43752 var tileZoom = 14;
43753 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43754 var mapillaryCache;
43755 var mapillaryClicks;
43756 var mapillaryImage;
43757 var mapillarySignDefs;
43758 var mapillaryViewer;
43759
43760
43761 function abortRequest(i) {
43762     i.abort();
43763 }
43764
43765
43766 function nearNullIsland(x, y, z) {
43767     if (z >= 7) {
43768         var center = Math.pow(2, z - 1),
43769             width = Math.pow(2, z - 6),
43770             min$$1 = center - (width / 2),
43771             max$$1 = center + (width / 2) - 1;
43772         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43773     }
43774     return false;
43775 }
43776
43777
43778 function maxPageAtZoom(z) {
43779     if (z < 15)   return 2;
43780     if (z === 15) return 5;
43781     if (z === 16) return 10;
43782     if (z === 17) return 20;
43783     if (z === 18) return 40;
43784     if (z > 18)   return 80;
43785 }
43786
43787
43788 function getTiles(projection) {
43789     var s = projection.scale() * 2 * Math.PI,
43790         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43791         ts = 256 * Math.pow(2, z - tileZoom),
43792         origin = [
43793             s / 2 - projection.translate()[0],
43794             s / 2 - projection.translate()[1]];
43795
43796     return d3geoTile()
43797         .scaleExtent([tileZoom, tileZoom])
43798         .scale(s)
43799         .size(projection.clipExtent()[1])
43800         .translate(projection.translate())()
43801         .map(function(tile) {
43802             var x = tile[0] * ts - origin[0],
43803                 y = tile[1] * ts - origin[1];
43804
43805             return {
43806                 id: tile.toString(),
43807                 xyz: tile,
43808                 extent: geoExtent$$1(
43809                     projection.invert([x, y + ts]),
43810                     projection.invert([x + ts, y])
43811                 )
43812             };
43813         });
43814 }
43815
43816
43817 function loadTiles(which, url, projection) {
43818     var s = projection.scale() * 2 * Math.PI,
43819         currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43820
43821     var tiles = getTiles(projection).filter(function(t) {
43822             return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43823         });
43824
43825     lodash.filter(which.inflight, function(v, k) {
43826         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43827         if (!wanted) delete which.inflight[k];
43828         return !wanted;
43829     }).map(abortRequest);
43830
43831     tiles.forEach(function(tile) {
43832         loadNextTilePage(which, currZoom, url, tile);
43833     });
43834 }
43835
43836
43837 function loadNextTilePage(which, currZoom, url, tile) {
43838     var cache = mapillaryCache[which],
43839         rect = tile.extent.rectangle(),
43840         maxPages = maxPageAtZoom(currZoom),
43841         nextPage = cache.nextPage[tile.id] || 0;
43842
43843     if (nextPage > maxPages) return;
43844
43845     var id = tile.id + ',' + String(nextPage);
43846     if (cache.loaded[id] || cache.inflight[id]) return;
43847
43848     cache.inflight[id] = json(url +
43849         utilQsString({
43850             geojson: 'true',
43851             limit: maxResults,
43852             page: nextPage,
43853             client_id: clientId,
43854             min_lon: rect[0],
43855             min_lat: rect[1],
43856             max_lon: rect[2],
43857             max_lat: rect[3]
43858         }), function(err, data) {
43859             cache.loaded[id] = true;
43860             delete cache.inflight[id];
43861             if (err || !data.features || !data.features.length) return;
43862
43863             var features = [],
43864                 feature, loc, d;
43865
43866             for (var i = 0; i < data.features.length; i++) {
43867                 feature = data.features[i];
43868                 loc = feature.geometry.coordinates;
43869                 d = { key: feature.properties.key, loc: loc };
43870                 if (which === 'images') d.ca = feature.properties.ca;
43871                 if (which === 'signs') d.signs = feature.properties.rects;
43872
43873                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43874             }
43875
43876             cache.rtree.load(features);
43877
43878             if (which === 'images') dispatch$2.call('loadedImages');
43879             if (which === 'signs') dispatch$2.call('loadedSigns');
43880
43881             if (data.features.length === maxResults) {  // more pages to load
43882                 cache.nextPage[tile.id] = nextPage + 1;
43883                 loadNextTilePage(which, currZoom, url, tile);
43884             } else {
43885                 cache.nextPage[tile.id] = Infinity;     // no more pages to load
43886             }
43887         }
43888     );
43889 }
43890
43891
43892 // partition viewport into `psize` x `psize` regions
43893 function partitionViewport(psize, projection) {
43894     var dimensions = projection.clipExtent()[1];
43895     psize = psize || 16;
43896     var cols = sequence(0, dimensions[0], psize),
43897         rows = sequence(0, dimensions[1], psize),
43898         partitions = [];
43899
43900     rows.forEach(function(y) {
43901         cols.forEach(function(x) {
43902             var min$$1 = [x, y + psize],
43903                 max$$1 = [x + psize, y];
43904             partitions.push(
43905                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43906         });
43907     });
43908
43909     return partitions;
43910 }
43911
43912
43913 // no more than `limit` results per partition.
43914 function searchLimited(psize, limit, projection, rtree) {
43915     limit = limit || 3;
43916
43917     var partitions = partitionViewport(psize, projection);
43918     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43919         return rtree.search(extent$$1.bbox())
43920             .slice(0, limit)
43921             .map(function(d) { return d.data; });
43922     })));
43923 }
43924
43925
43926
43927 var serviceMapillary = {
43928
43929     init: function() {
43930         if (!mapillaryCache) {
43931             this.reset();
43932         }
43933
43934         this.event = utilRebind(this, dispatch$2, 'on');
43935     },
43936
43937     reset: function() {
43938         var cache = mapillaryCache;
43939
43940         if (cache) {
43941             if (cache.images && cache.images.inflight) {
43942                 lodash.forEach(cache.images.inflight, abortRequest);
43943             }
43944             if (cache.signs && cache.signs.inflight) {
43945                 lodash.forEach(cache.signs.inflight, abortRequest);
43946             }
43947         }
43948
43949         mapillaryCache = {
43950             images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() },
43951             signs:  { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() }
43952         };
43953
43954         mapillaryImage = null;
43955         mapillaryClicks = [];
43956     },
43957
43958
43959     images: function(projection) {
43960         var psize = 16, limit = 3;
43961         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43962     },
43963
43964
43965     signs: function(projection) {
43966         var psize = 32, limit = 3;
43967         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43968     },
43969
43970
43971     signsSupported: function() {
43972         var detected = utilDetect();
43973         if (detected.ie) return false;
43974         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43975         return true;
43976     },
43977
43978
43979     signHTML: function(d) {
43980         if (!mapillarySignDefs) return;
43981
43982         var detectionPackage = d.signs[0].package,
43983             type = d.signs[0].type,
43984             country = detectionPackage.split('_')[1];
43985
43986         return mapillarySignDefs[country][type];
43987     },
43988
43989
43990     loadImages: function(projection) {
43991         var url = apibase + 'search/im/geojson?';
43992         loadTiles('images', url, projection);
43993     },
43994
43995
43996     loadSigns: function(context, projection) {
43997         var url = apibase + 'search/im/geojson/or?';
43998         loadTiles('signs', url, projection);
43999
44000         // load traffico css
44001         select('head').selectAll('#traffico')
44002             .data([0])
44003             .enter()
44004             .append('link')
44005             .attr('id', 'traffico')
44006             .attr('rel', 'stylesheet')
44007             .attr('href', context.asset(trafficocss));
44008
44009         // load traffico sign defs
44010         if (!mapillarySignDefs) {
44011             mapillarySignDefs = {};
44012             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
44013                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
44014                     if (err) return;
44015                     if (region === 'de') region = 'eu';
44016                     mapillarySignDefs[region] = data;
44017                 });
44018             });
44019         }
44020     },
44021
44022
44023     loadViewer: function(context) {
44024         var that = this;
44025         var wrap = select('#content').selectAll('.mapillary-wrap')
44026             .data([0]);
44027
44028         var enter = wrap.enter()
44029             .append('div')
44030             .attr('class', 'mapillary-wrap')
44031             .classed('al', true)       // 'al'=left,  'ar'=right
44032             .classed('hidden', true);
44033
44034         enter
44035             .append('button')
44036             .attr('class', 'thumb-hide')
44037             .on('click', function () { that.hideViewer(); })
44038             .append('div')
44039             .call(svgIcon('#icon-close'));
44040
44041         enter
44042             .append('div')
44043             .attr('id', 'mly')
44044             .attr('class', 'mly-wrapper')
44045             .classed('active', false);
44046
44047         // load mapillary-viewercss
44048         select('head').selectAll('#mapillary-viewercss')
44049             .data([0])
44050             .enter()
44051             .append('link')
44052             .attr('id', 'mapillary-viewercss')
44053             .attr('rel', 'stylesheet')
44054             .attr('href', context.asset(viewercss));
44055
44056         // load mapillary-viewerjs
44057         select('head').selectAll('#mapillary-viewerjs')
44058             .data([0])
44059             .enter()
44060             .append('script')
44061             .attr('id', 'mapillary-viewerjs')
44062             .attr('src', context.asset(viewerjs));
44063     },
44064
44065
44066     showViewer: function() {
44067         select('#content')
44068             .selectAll('.mapillary-wrap')
44069             .classed('hidden', false)
44070             .selectAll('.mly-wrapper')
44071             .classed('active', true);
44072
44073         return this;
44074     },
44075
44076
44077     hideViewer: function() {
44078         select('#content')
44079             .selectAll('.mapillary-wrap')
44080             .classed('hidden', true)
44081             .selectAll('.mly-wrapper')
44082             .classed('active', false);
44083
44084         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44085             .classed('selected', false);
44086
44087         mapillaryImage = null;
44088         return this;
44089     },
44090
44091
44092     updateViewer: function(imageKey, context) {
44093         if (!imageKey) return;
44094
44095         if (!mapillaryViewer) {
44096             this.initViewer(imageKey, context);
44097         } else {
44098             mapillaryViewer.moveToKey(imageKey);
44099         }
44100
44101         return this;
44102     },
44103
44104
44105     initViewer: function(imageKey, context) {
44106         var that = this;
44107         if (Mapillary && imageKey) {
44108             var opts = {
44109                 baseImageSize: 320,
44110                 component: {
44111                     cover: false,
44112                     keyboard: false
44113                 }
44114             };
44115
44116             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44117             mapillaryViewer.on('nodechanged', nodeChanged);
44118         }
44119
44120         function nodeChanged(node) {
44121             var clicks = mapillaryClicks;
44122             var index = clicks.indexOf(node.key);
44123             if (index > -1) {    // nodechange initiated from clicking on a marker..
44124                 clicks.splice(index, 1);
44125             } else {             // nodechange initiated from the Mapillary viewer controls..
44126                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44127                 context.map().centerEase(loc);
44128                 that.selectedImage(node.key, false);
44129             }
44130         }
44131     },
44132
44133
44134     selectedImage: function(imageKey, fromClick) {
44135         if (!arguments.length) return mapillaryImage;
44136
44137         mapillaryImage = imageKey;
44138         if (fromClick) {
44139             mapillaryClicks.push(imageKey);
44140         }
44141
44142         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44143             .classed('selected', function(d) { return d.key === imageKey; });
44144
44145         return this;
44146     },
44147
44148
44149     cache: function(_) {
44150         if (!arguments.length) return mapillaryCache;
44151         mapillaryCache = _;
44152         return this;
44153     },
44154
44155
44156     signDefs: function(_) {
44157         if (!arguments.length) return mapillarySignDefs;
44158         mapillarySignDefs = _;
44159         return this;
44160     }
44161
44162 };
44163
44164 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44165 var nominatimCache;
44166
44167
44168 var serviceNominatim = {
44169
44170     init: function() { nominatimCache = index$9(); },
44171     reset: function() { nominatimCache = index$9(); },
44172
44173
44174     countryCode: function (location, callback) {
44175         var countryCodes = nominatimCache.search(
44176             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44177         );
44178
44179         if (countryCodes.length > 0) {
44180             return callback(null, countryCodes[0].data);
44181         }
44182
44183         json(apibase$1 + 'reverse?' +
44184             utilQsString({
44185                 format: 'json',
44186                 addressdetails: 1,
44187                 lat: location[1],
44188                 lon: location[0]
44189             }), function(err, result) {
44190                 if (err)
44191                     return callback(err);
44192                 else if (result && result.error)
44193                     return callback(result.error);
44194
44195                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
44196                 nominatimCache.insert(lodash.assign(extent$$1.bbox(),
44197                     { data: result.address.country_code }
44198                 ));
44199
44200                 callback(null, result.address.country_code);
44201             }
44202         );
44203     },
44204
44205
44206     search: function (val, callback) {
44207         var searchVal = encodeURIComponent(val);
44208         json(apibase$1 + 'search/' + searchVal + '?limit=10&format=json', callback);
44209     }
44210
44211 };
44212
44213 var hashes$1 = createCommonjsModule(function (module, exports) {
44214 /**
44215  * jshashes - https://github.com/h2non/jshashes
44216  * Released under the "New BSD" license
44217  *
44218  * Algorithms specification:
44219  *
44220  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44221  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44222  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44223  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44224  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44225  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44226  */
44227 (function() {
44228   var Hashes;
44229
44230   function utf8Encode(str) {
44231     var x, y, output = '',
44232       i = -1,
44233       l;
44234
44235     if (str && str.length) {
44236       l = str.length;
44237       while ((i += 1) < l) {
44238         /* Decode utf-16 surrogate pairs */
44239         x = str.charCodeAt(i);
44240         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44241         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44242           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44243           i += 1;
44244         }
44245         /* Encode output as utf-8 */
44246         if (x <= 0x7F) {
44247           output += String.fromCharCode(x);
44248         } else if (x <= 0x7FF) {
44249           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44250             0x80 | (x & 0x3F));
44251         } else if (x <= 0xFFFF) {
44252           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44253             0x80 | ((x >>> 6) & 0x3F),
44254             0x80 | (x & 0x3F));
44255         } else if (x <= 0x1FFFFF) {
44256           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44257             0x80 | ((x >>> 12) & 0x3F),
44258             0x80 | ((x >>> 6) & 0x3F),
44259             0x80 | (x & 0x3F));
44260         }
44261       }
44262     }
44263     return output;
44264   }
44265
44266   function utf8Decode(str) {
44267     var i, ac, c1, c2, c3, arr = [],
44268       l;
44269     i = ac = c1 = c2 = c3 = 0;
44270
44271     if (str && str.length) {
44272       l = str.length;
44273       str += '';
44274
44275       while (i < l) {
44276         c1 = str.charCodeAt(i);
44277         ac += 1;
44278         if (c1 < 128) {
44279           arr[ac] = String.fromCharCode(c1);
44280           i += 1;
44281         } else if (c1 > 191 && c1 < 224) {
44282           c2 = str.charCodeAt(i + 1);
44283           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44284           i += 2;
44285         } else {
44286           c2 = str.charCodeAt(i + 1);
44287           c3 = str.charCodeAt(i + 2);
44288           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44289           i += 3;
44290         }
44291       }
44292     }
44293     return arr.join('');
44294   }
44295
44296   /**
44297    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44298    * to work around bugs in some JS interpreters.
44299    */
44300
44301   function safe_add(x, y) {
44302     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44303       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44304     return (msw << 16) | (lsw & 0xFFFF);
44305   }
44306
44307   /**
44308    * Bitwise rotate a 32-bit number to the left.
44309    */
44310
44311   function bit_rol(num, cnt) {
44312     return (num << cnt) | (num >>> (32 - cnt));
44313   }
44314
44315   /**
44316    * Convert a raw string to a hex string
44317    */
44318
44319   function rstr2hex(input, hexcase) {
44320     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44321       output = '',
44322       x, i = 0,
44323       l = input.length;
44324     for (; i < l; i += 1) {
44325       x = input.charCodeAt(i);
44326       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44327     }
44328     return output;
44329   }
44330
44331   /**
44332    * Encode a string as utf-16
44333    */
44334
44335   function binb2rstr(input) {
44336     var i, l = input.length * 32,
44337       output = '';
44338     for (i = 0; i < l; i += 8) {
44339       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44340     }
44341     return output;
44342   }
44343
44344   /**
44345    * Convert an array of little-endian words to a string
44346    */
44347
44348   function binl2rstr(input) {
44349     var i, l = input.length * 32,
44350       output = '';
44351     for (i = 0; i < l; i += 8) {
44352       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44353     }
44354     return output;
44355   }
44356
44357   /**
44358    * Convert a raw string to an array of little-endian words
44359    * Characters >255 have their high-byte silently ignored.
44360    */
44361
44362   function rstr2binl(input) {
44363     var i, l = input.length * 8,
44364       output = Array(input.length >> 2),
44365       lo = output.length;
44366     for (i = 0; i < lo; i += 1) {
44367       output[i] = 0;
44368     }
44369     for (i = 0; i < l; i += 8) {
44370       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44371     }
44372     return output;
44373   }
44374
44375   /**
44376    * Convert a raw string to an array of big-endian words
44377    * Characters >255 have their high-byte silently ignored.
44378    */
44379
44380   function rstr2binb(input) {
44381     var i, l = input.length * 8,
44382       output = Array(input.length >> 2),
44383       lo = output.length;
44384     for (i = 0; i < lo; i += 1) {
44385       output[i] = 0;
44386     }
44387     for (i = 0; i < l; i += 8) {
44388       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44389     }
44390     return output;
44391   }
44392
44393   /**
44394    * Convert a raw string to an arbitrary string encoding
44395    */
44396
44397   function rstr2any(input, encoding) {
44398     var divisor = encoding.length,
44399       remainders = Array(),
44400       i, q, x, ld, quotient, dividend, output, full_length;
44401
44402     /* Convert to an array of 16-bit big-endian values, forming the dividend */
44403     dividend = Array(Math.ceil(input.length / 2));
44404     ld = dividend.length;
44405     for (i = 0; i < ld; i += 1) {
44406       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44407     }
44408
44409     /**
44410      * Repeatedly perform a long division. The binary array forms the dividend,
44411      * the length of the encoding is the divisor. Once computed, the quotient
44412      * forms the dividend for the next step. We stop when the dividend is zerHashes.
44413      * All remainders are stored for later use.
44414      */
44415     while (dividend.length > 0) {
44416       quotient = Array();
44417       x = 0;
44418       for (i = 0; i < dividend.length; i += 1) {
44419         x = (x << 16) + dividend[i];
44420         q = Math.floor(x / divisor);
44421         x -= q * divisor;
44422         if (quotient.length > 0 || q > 0) {
44423           quotient[quotient.length] = q;
44424         }
44425       }
44426       remainders[remainders.length] = x;
44427       dividend = quotient;
44428     }
44429
44430     /* Convert the remainders to the output string */
44431     output = '';
44432     for (i = remainders.length - 1; i >= 0; i--) {
44433       output += encoding.charAt(remainders[i]);
44434     }
44435
44436     /* Append leading zero equivalents */
44437     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
44438     for (i = output.length; i < full_length; i += 1) {
44439       output = encoding[0] + output;
44440     }
44441     return output;
44442   }
44443
44444   /**
44445    * Convert a raw string to a base-64 string
44446    */
44447
44448   function rstr2b64(input, b64pad) {
44449     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44450       output = '',
44451       len = input.length,
44452       i, j, triplet;
44453     b64pad = b64pad || '=';
44454     for (i = 0; i < len; i += 3) {
44455       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44456       for (j = 0; j < 4; j += 1) {
44457         if (i * 8 + j * 6 > input.length * 8) {
44458           output += b64pad;
44459         } else {
44460           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44461         }
44462       }
44463     }
44464     return output;
44465   }
44466
44467   Hashes = {
44468     /**
44469      * @property {String} version
44470      * @readonly
44471      */
44472     VERSION: '1.0.5',
44473     /**
44474      * @member Hashes
44475      * @class Base64
44476      * @constructor
44477      */
44478     Base64: function() {
44479       // private properties
44480       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44481         pad = '=', // default pad according with the RFC standard
44482         url = false, // URL encoding support @todo
44483         utf8 = true; // by default enable UTF-8 support encoding
44484
44485       // public method for encoding
44486       this.encode = function(input) {
44487         var i, j, triplet,
44488           output = '',
44489           len = input.length;
44490
44491         pad = pad || '=';
44492         input = (utf8) ? utf8Encode(input) : input;
44493
44494         for (i = 0; i < len; i += 3) {
44495           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44496           for (j = 0; j < 4; j += 1) {
44497             if (i * 8 + j * 6 > len * 8) {
44498               output += pad;
44499             } else {
44500               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44501             }
44502           }
44503         }
44504         return output;
44505       };
44506
44507       // public method for decoding
44508       this.decode = function(input) {
44509         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
44510         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
44511           dec = '',
44512           arr = [];
44513         if (!input) {
44514           return input;
44515         }
44516
44517         i = ac = 0;
44518         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
44519         //input += '';
44520
44521         do { // unpack four hexets into three octets using index points in b64
44522           h1 = tab.indexOf(input.charAt(i += 1));
44523           h2 = tab.indexOf(input.charAt(i += 1));
44524           h3 = tab.indexOf(input.charAt(i += 1));
44525           h4 = tab.indexOf(input.charAt(i += 1));
44526
44527           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
44528
44529           o1 = bits >> 16 & 0xff;
44530           o2 = bits >> 8 & 0xff;
44531           o3 = bits & 0xff;
44532           ac += 1;
44533
44534           if (h3 === 64) {
44535             arr[ac] = String.fromCharCode(o1);
44536           } else if (h4 === 64) {
44537             arr[ac] = String.fromCharCode(o1, o2);
44538           } else {
44539             arr[ac] = String.fromCharCode(o1, o2, o3);
44540           }
44541         } while (i < input.length);
44542
44543         dec = arr.join('');
44544         dec = (utf8) ? utf8Decode(dec) : dec;
44545
44546         return dec;
44547       };
44548
44549       // set custom pad string
44550       this.setPad = function(str) {
44551         pad = str || pad;
44552         return this;
44553       };
44554       // set custom tab string characters
44555       this.setTab = function(str) {
44556         tab = str || tab;
44557         return this;
44558       };
44559       this.setUTF8 = function(bool) {
44560         if (typeof bool === 'boolean') {
44561           utf8 = bool;
44562         }
44563         return this;
44564       };
44565     },
44566
44567     /**
44568      * CRC-32 calculation
44569      * @member Hashes
44570      * @method CRC32
44571      * @static
44572      * @param {String} str Input String
44573      * @return {String}
44574      */
44575     CRC32: function(str) {
44576       var crc = 0,
44577         x = 0,
44578         y = 0,
44579         table, i, iTop;
44580       str = utf8Encode(str);
44581
44582       table = [
44583         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44584         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44585         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44586         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44587         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44588         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44589         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44590         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44591         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44592         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44593         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44594         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44595         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44596         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44597         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44598         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44599         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44600         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44601         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44602         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44603         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44604         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44605         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44606         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44607         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44608         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44609       ].join('');
44610
44611       crc = crc ^ (-1);
44612       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44613         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44614         x = '0x' + table.substr(y * 9, 8);
44615         crc = (crc >>> 8) ^ x;
44616       }
44617       // always return a positive number (that's what >>> 0 does)
44618       return (crc ^ (-1)) >>> 0;
44619     },
44620     /**
44621      * @member Hashes
44622      * @class MD5
44623      * @constructor
44624      * @param {Object} [config]
44625      *
44626      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44627      * Digest Algorithm, as defined in RFC 1321.
44628      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44629      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44630      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44631      */
44632     MD5: function(options) {
44633       /**
44634        * Private config properties. You may need to tweak these to be compatible with
44635        * the server-side, but the defaults work in most cases.
44636        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44637        */
44638       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44639         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44640         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44641
44642       // privileged (public) methods
44643       this.hex = function(s) {
44644         return rstr2hex(rstr(s, utf8), hexcase);
44645       };
44646       this.b64 = function(s) {
44647         return rstr2b64(rstr(s), b64pad);
44648       };
44649       this.any = function(s, e) {
44650         return rstr2any(rstr(s, utf8), e);
44651       };
44652       this.raw = function(s) {
44653         return rstr(s, utf8);
44654       };
44655       this.hex_hmac = function(k, d) {
44656         return rstr2hex(rstr_hmac(k, d), hexcase);
44657       };
44658       this.b64_hmac = function(k, d) {
44659         return rstr2b64(rstr_hmac(k, d), b64pad);
44660       };
44661       this.any_hmac = function(k, d, e) {
44662         return rstr2any(rstr_hmac(k, d), e);
44663       };
44664       /**
44665        * Perform a simple self-test to see if the VM is working
44666        * @return {String} Hexadecimal hash sample
44667        */
44668       this.vm_test = function() {
44669         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44670       };
44671       /**
44672        * Enable/disable uppercase hexadecimal returned string
44673        * @param {Boolean}
44674        * @return {Object} this
44675        */
44676       this.setUpperCase = function(a) {
44677         if (typeof a === 'boolean') {
44678           hexcase = a;
44679         }
44680         return this;
44681       };
44682       /**
44683        * Defines a base64 pad string
44684        * @param {String} Pad
44685        * @return {Object} this
44686        */
44687       this.setPad = function(a) {
44688         b64pad = a || b64pad;
44689         return this;
44690       };
44691       /**
44692        * Defines a base64 pad string
44693        * @param {Boolean}
44694        * @return {Object} [this]
44695        */
44696       this.setUTF8 = function(a) {
44697         if (typeof a === 'boolean') {
44698           utf8 = a;
44699         }
44700         return this;
44701       };
44702
44703       // private methods
44704
44705       /**
44706        * Calculate the MD5 of a raw string
44707        */
44708
44709       function rstr(s) {
44710         s = (utf8) ? utf8Encode(s) : s;
44711         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44712       }
44713
44714       /**
44715        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44716        */
44717
44718       function rstr_hmac(key, data) {
44719         var bkey, ipad, opad, hash, i;
44720
44721         key = (utf8) ? utf8Encode(key) : key;
44722         data = (utf8) ? utf8Encode(data) : data;
44723         bkey = rstr2binl(key);
44724         if (bkey.length > 16) {
44725           bkey = binl(bkey, key.length * 8);
44726         }
44727
44728         ipad = Array(16), opad = Array(16);
44729         for (i = 0; i < 16; i += 1) {
44730           ipad[i] = bkey[i] ^ 0x36363636;
44731           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44732         }
44733         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44734         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44735       }
44736
44737       /**
44738        * Calculate the MD5 of an array of little-endian words, and a bit length.
44739        */
44740
44741       function binl(x, len) {
44742         var i, olda, oldb, oldc, oldd,
44743           a = 1732584193,
44744           b = -271733879,
44745           c = -1732584194,
44746           d = 271733878;
44747
44748         /* append padding */
44749         x[len >> 5] |= 0x80 << ((len) % 32);
44750         x[(((len + 64) >>> 9) << 4) + 14] = len;
44751
44752         for (i = 0; i < x.length; i += 16) {
44753           olda = a;
44754           oldb = b;
44755           oldc = c;
44756           oldd = d;
44757
44758           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44759           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44760           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44761           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44762           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44763           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44764           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44765           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44766           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44767           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44768           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44769           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44770           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44771           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44772           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44773           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44774
44775           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44776           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44777           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44778           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44779           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44780           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44781           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44782           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44783           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44784           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44785           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44786           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44787           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44788           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44789           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44790           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44791
44792           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44793           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44794           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44795           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44796           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44797           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44798           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44799           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44800           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44801           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44802           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44803           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44804           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44805           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44806           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44807           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44808
44809           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44810           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44811           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44812           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44813           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44814           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44815           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44816           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44817           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44818           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44819           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44820           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44821           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44822           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44823           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44824           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44825
44826           a = safe_add(a, olda);
44827           b = safe_add(b, oldb);
44828           c = safe_add(c, oldc);
44829           d = safe_add(d, oldd);
44830         }
44831         return Array(a, b, c, d);
44832       }
44833
44834       /**
44835        * These functions implement the four basic operations the algorithm uses.
44836        */
44837
44838       function md5_cmn(q, a, b, x, s, t) {
44839         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44840       }
44841
44842       function md5_ff(a, b, c, d, x, s, t) {
44843         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44844       }
44845
44846       function md5_gg(a, b, c, d, x, s, t) {
44847         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44848       }
44849
44850       function md5_hh(a, b, c, d, x, s, t) {
44851         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44852       }
44853
44854       function md5_ii(a, b, c, d, x, s, t) {
44855         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44856       }
44857     },
44858     /**
44859      * @member Hashes
44860      * @class Hashes.SHA1
44861      * @param {Object} [config]
44862      * @constructor
44863      *
44864      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44865      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44866      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44867      * See http://pajhome.org.uk/crypt/md5 for details.
44868      */
44869     SHA1: function(options) {
44870       /**
44871        * Private config properties. You may need to tweak these to be compatible with
44872        * the server-side, but the defaults work in most cases.
44873        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44874        */
44875       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44876         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44877         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44878
44879       // public methods
44880       this.hex = function(s) {
44881         return rstr2hex(rstr(s, utf8), hexcase);
44882       };
44883       this.b64 = function(s) {
44884         return rstr2b64(rstr(s, utf8), b64pad);
44885       };
44886       this.any = function(s, e) {
44887         return rstr2any(rstr(s, utf8), e);
44888       };
44889       this.raw = function(s) {
44890         return rstr(s, utf8);
44891       };
44892       this.hex_hmac = function(k, d) {
44893         return rstr2hex(rstr_hmac(k, d));
44894       };
44895       this.b64_hmac = function(k, d) {
44896         return rstr2b64(rstr_hmac(k, d), b64pad);
44897       };
44898       this.any_hmac = function(k, d, e) {
44899         return rstr2any(rstr_hmac(k, d), e);
44900       };
44901       /**
44902        * Perform a simple self-test to see if the VM is working
44903        * @return {String} Hexadecimal hash sample
44904        * @public
44905        */
44906       this.vm_test = function() {
44907         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44908       };
44909       /**
44910        * @description Enable/disable uppercase hexadecimal returned string
44911        * @param {boolean}
44912        * @return {Object} this
44913        * @public
44914        */
44915       this.setUpperCase = function(a) {
44916         if (typeof a === 'boolean') {
44917           hexcase = a;
44918         }
44919         return this;
44920       };
44921       /**
44922        * @description Defines a base64 pad string
44923        * @param {string} Pad
44924        * @return {Object} this
44925        * @public
44926        */
44927       this.setPad = function(a) {
44928         b64pad = a || b64pad;
44929         return this;
44930       };
44931       /**
44932        * @description Defines a base64 pad string
44933        * @param {boolean}
44934        * @return {Object} this
44935        * @public
44936        */
44937       this.setUTF8 = function(a) {
44938         if (typeof a === 'boolean') {
44939           utf8 = a;
44940         }
44941         return this;
44942       };
44943
44944       // private methods
44945
44946       /**
44947        * Calculate the SHA-512 of a raw string
44948        */
44949
44950       function rstr(s) {
44951         s = (utf8) ? utf8Encode(s) : s;
44952         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44953       }
44954
44955       /**
44956        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44957        */
44958
44959       function rstr_hmac(key, data) {
44960         var bkey, ipad, opad, i, hash;
44961         key = (utf8) ? utf8Encode(key) : key;
44962         data = (utf8) ? utf8Encode(data) : data;
44963         bkey = rstr2binb(key);
44964
44965         if (bkey.length > 16) {
44966           bkey = binb(bkey, key.length * 8);
44967         }
44968         ipad = Array(16), opad = Array(16);
44969         for (i = 0; i < 16; i += 1) {
44970           ipad[i] = bkey[i] ^ 0x36363636;
44971           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44972         }
44973         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44974         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44975       }
44976
44977       /**
44978        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44979        */
44980
44981       function binb(x, len) {
44982         var i, j, t, olda, oldb, oldc, oldd, olde,
44983           w = Array(80),
44984           a = 1732584193,
44985           b = -271733879,
44986           c = -1732584194,
44987           d = 271733878,
44988           e = -1009589776;
44989
44990         /* append padding */
44991         x[len >> 5] |= 0x80 << (24 - len % 32);
44992         x[((len + 64 >> 9) << 4) + 15] = len;
44993
44994         for (i = 0; i < x.length; i += 16) {
44995           olda = a,
44996           oldb = b;
44997           oldc = c;
44998           oldd = d;
44999           olde = e;
45000
45001           for (j = 0; j < 80; j += 1) {
45002             if (j < 16) {
45003               w[j] = x[i + j];
45004             } else {
45005               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
45006             }
45007             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
45008               safe_add(safe_add(e, w[j]), sha1_kt(j)));
45009             e = d;
45010             d = c;
45011             c = bit_rol(b, 30);
45012             b = a;
45013             a = t;
45014           }
45015
45016           a = safe_add(a, olda);
45017           b = safe_add(b, oldb);
45018           c = safe_add(c, oldc);
45019           d = safe_add(d, oldd);
45020           e = safe_add(e, olde);
45021         }
45022         return Array(a, b, c, d, e);
45023       }
45024
45025       /**
45026        * Perform the appropriate triplet combination function for the current
45027        * iteration
45028        */
45029
45030       function sha1_ft(t, b, c, d) {
45031         if (t < 20) {
45032           return (b & c) | ((~b) & d);
45033         }
45034         if (t < 40) {
45035           return b ^ c ^ d;
45036         }
45037         if (t < 60) {
45038           return (b & c) | (b & d) | (c & d);
45039         }
45040         return b ^ c ^ d;
45041       }
45042
45043       /**
45044        * Determine the appropriate additive constant for the current iteration
45045        */
45046
45047       function sha1_kt(t) {
45048         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
45049           (t < 60) ? -1894007588 : -899497514;
45050       }
45051     },
45052     /**
45053      * @class Hashes.SHA256
45054      * @param {config}
45055      *
45056      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45057      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45058      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45059      * See http://pajhome.org.uk/crypt/md5 for details.
45060      * Also http://anmar.eu.org/projects/jssha2/
45061      */
45062     SHA256: function(options) {
45063       /**
45064        * Private properties configuration variables. You may need to tweak these to be compatible with
45065        * the server-side, but the defaults work in most cases.
45066        * @see this.setUpperCase() method
45067        * @see this.setPad() method
45068        */
45069       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
45070         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45071         /* base-64 pad character. Default '=' for strict RFC compliance   */
45072         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45073         /* enable/disable utf8 encoding */
45074         sha256_K;
45075
45076       /* privileged (public) methods */
45077       this.hex = function(s) {
45078         return rstr2hex(rstr(s, utf8));
45079       };
45080       this.b64 = function(s) {
45081         return rstr2b64(rstr(s, utf8), b64pad);
45082       };
45083       this.any = function(s, e) {
45084         return rstr2any(rstr(s, utf8), e);
45085       };
45086       this.raw = function(s) {
45087         return rstr(s, utf8);
45088       };
45089       this.hex_hmac = function(k, d) {
45090         return rstr2hex(rstr_hmac(k, d));
45091       };
45092       this.b64_hmac = function(k, d) {
45093         return rstr2b64(rstr_hmac(k, d), b64pad);
45094       };
45095       this.any_hmac = function(k, d, e) {
45096         return rstr2any(rstr_hmac(k, d), e);
45097       };
45098       /**
45099        * Perform a simple self-test to see if the VM is working
45100        * @return {String} Hexadecimal hash sample
45101        * @public
45102        */
45103       this.vm_test = function() {
45104         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45105       };
45106       /**
45107        * Enable/disable uppercase hexadecimal returned string
45108        * @param {boolean}
45109        * @return {Object} this
45110        * @public
45111        */
45112       this.setUpperCase = function(a) {
45113         if (typeof a === 'boolean') {
45114           hexcase = a;
45115         }
45116         return this;
45117       };
45118       /**
45119        * @description Defines a base64 pad string
45120        * @param {string} Pad
45121        * @return {Object} this
45122        * @public
45123        */
45124       this.setPad = function(a) {
45125         b64pad = a || b64pad;
45126         return this;
45127       };
45128       /**
45129        * Defines a base64 pad string
45130        * @param {boolean}
45131        * @return {Object} this
45132        * @public
45133        */
45134       this.setUTF8 = function(a) {
45135         if (typeof a === 'boolean') {
45136           utf8 = a;
45137         }
45138         return this;
45139       };
45140
45141       // private methods
45142
45143       /**
45144        * Calculate the SHA-512 of a raw string
45145        */
45146
45147       function rstr(s, utf8) {
45148         s = (utf8) ? utf8Encode(s) : s;
45149         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45150       }
45151
45152       /**
45153        * Calculate the HMAC-sha256 of a key and some data (raw strings)
45154        */
45155
45156       function rstr_hmac(key, data) {
45157         key = (utf8) ? utf8Encode(key) : key;
45158         data = (utf8) ? utf8Encode(data) : data;
45159         var hash, i = 0,
45160           bkey = rstr2binb(key),
45161           ipad = Array(16),
45162           opad = Array(16);
45163
45164         if (bkey.length > 16) {
45165           bkey = binb(bkey, key.length * 8);
45166         }
45167
45168         for (; i < 16; i += 1) {
45169           ipad[i] = bkey[i] ^ 0x36363636;
45170           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45171         }
45172
45173         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45174         return binb2rstr(binb(opad.concat(hash), 512 + 256));
45175       }
45176
45177       /*
45178        * Main sha256 function, with its support functions
45179        */
45180
45181       function sha256_S(X, n) {
45182         return (X >>> n) | (X << (32 - n));
45183       }
45184
45185       function sha256_R(X, n) {
45186         return (X >>> n);
45187       }
45188
45189       function sha256_Ch(x, y, z) {
45190         return ((x & y) ^ ((~x) & z));
45191       }
45192
45193       function sha256_Maj(x, y, z) {
45194         return ((x & y) ^ (x & z) ^ (y & z));
45195       }
45196
45197       function sha256_Sigma0256(x) {
45198         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45199       }
45200
45201       function sha256_Sigma1256(x) {
45202         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45203       }
45204
45205       function sha256_Gamma0256(x) {
45206         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45207       }
45208
45209       function sha256_Gamma1256(x) {
45210         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45211       }
45212
45213       sha256_K = [
45214         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45215         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45216         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45217         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45218         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45219         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45220         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45221       ];
45222
45223       function binb(m, l) {
45224         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45225           1359893119, -1694144372, 528734635, 1541459225
45226         ];
45227         var W = new Array(64);
45228         var a, b, c, d, e, f, g, h;
45229         var i, j, T1, T2;
45230
45231         /* append padding */
45232         m[l >> 5] |= 0x80 << (24 - l % 32);
45233         m[((l + 64 >> 9) << 4) + 15] = l;
45234
45235         for (i = 0; i < m.length; i += 16) {
45236           a = HASH[0];
45237           b = HASH[1];
45238           c = HASH[2];
45239           d = HASH[3];
45240           e = HASH[4];
45241           f = HASH[5];
45242           g = HASH[6];
45243           h = HASH[7];
45244
45245           for (j = 0; j < 64; j += 1) {
45246             if (j < 16) {
45247               W[j] = m[j + i];
45248             } else {
45249               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45250                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45251             }
45252
45253             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45254               sha256_K[j]), W[j]);
45255             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45256             h = g;
45257             g = f;
45258             f = e;
45259             e = safe_add(d, T1);
45260             d = c;
45261             c = b;
45262             b = a;
45263             a = safe_add(T1, T2);
45264           }
45265
45266           HASH[0] = safe_add(a, HASH[0]);
45267           HASH[1] = safe_add(b, HASH[1]);
45268           HASH[2] = safe_add(c, HASH[2]);
45269           HASH[3] = safe_add(d, HASH[3]);
45270           HASH[4] = safe_add(e, HASH[4]);
45271           HASH[5] = safe_add(f, HASH[5]);
45272           HASH[6] = safe_add(g, HASH[6]);
45273           HASH[7] = safe_add(h, HASH[7]);
45274         }
45275         return HASH;
45276       }
45277
45278     },
45279
45280     /**
45281      * @class Hashes.SHA512
45282      * @param {config}
45283      *
45284      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45285      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45286      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45287      * See http://pajhome.org.uk/crypt/md5 for details.
45288      */
45289     SHA512: function(options) {
45290       /**
45291        * Private properties configuration variables. You may need to tweak these to be compatible with
45292        * the server-side, but the defaults work in most cases.
45293        * @see this.setUpperCase() method
45294        * @see this.setPad() method
45295        */
45296       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45297         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45298         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45299         /* base-64 pad character. Default '=' for strict RFC compliance   */
45300         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45301         /* enable/disable utf8 encoding */
45302         sha512_k;
45303
45304       /* privileged (public) methods */
45305       this.hex = function(s) {
45306         return rstr2hex(rstr(s));
45307       };
45308       this.b64 = function(s) {
45309         return rstr2b64(rstr(s), b64pad);
45310       };
45311       this.any = function(s, e) {
45312         return rstr2any(rstr(s), e);
45313       };
45314       this.raw = function(s) {
45315         return rstr(s, utf8);
45316       };
45317       this.hex_hmac = function(k, d) {
45318         return rstr2hex(rstr_hmac(k, d));
45319       };
45320       this.b64_hmac = function(k, d) {
45321         return rstr2b64(rstr_hmac(k, d), b64pad);
45322       };
45323       this.any_hmac = function(k, d, e) {
45324         return rstr2any(rstr_hmac(k, d), e);
45325       };
45326       /**
45327        * Perform a simple self-test to see if the VM is working
45328        * @return {String} Hexadecimal hash sample
45329        * @public
45330        */
45331       this.vm_test = function() {
45332         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45333       };
45334       /**
45335        * @description Enable/disable uppercase hexadecimal returned string
45336        * @param {boolean}
45337        * @return {Object} this
45338        * @public
45339        */
45340       this.setUpperCase = function(a) {
45341         if (typeof a === 'boolean') {
45342           hexcase = a;
45343         }
45344         return this;
45345       };
45346       /**
45347        * @description Defines a base64 pad string
45348        * @param {string} Pad
45349        * @return {Object} this
45350        * @public
45351        */
45352       this.setPad = function(a) {
45353         b64pad = a || b64pad;
45354         return this;
45355       };
45356       /**
45357        * @description Defines a base64 pad string
45358        * @param {boolean}
45359        * @return {Object} this
45360        * @public
45361        */
45362       this.setUTF8 = function(a) {
45363         if (typeof a === 'boolean') {
45364           utf8 = a;
45365         }
45366         return this;
45367       };
45368
45369       /* private methods */
45370
45371       /**
45372        * Calculate the SHA-512 of a raw string
45373        */
45374
45375       function rstr(s) {
45376         s = (utf8) ? utf8Encode(s) : s;
45377         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45378       }
45379       /*
45380        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45381        */
45382
45383       function rstr_hmac(key, data) {
45384         key = (utf8) ? utf8Encode(key) : key;
45385         data = (utf8) ? utf8Encode(data) : data;
45386
45387         var hash, i = 0,
45388           bkey = rstr2binb(key),
45389           ipad = Array(32),
45390           opad = Array(32);
45391
45392         if (bkey.length > 32) {
45393           bkey = binb(bkey, key.length * 8);
45394         }
45395
45396         for (; i < 32; i += 1) {
45397           ipad[i] = bkey[i] ^ 0x36363636;
45398           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45399         }
45400
45401         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45402         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45403       }
45404
45405       /**
45406        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45407        */
45408
45409       function binb(x, len) {
45410         var j, i, l,
45411           W = new Array(80),
45412           hash = new Array(16),
45413           //Initial hash values
45414           H = [
45415             new int64(0x6a09e667, -205731576),
45416             new int64(-1150833019, -2067093701),
45417             new int64(0x3c6ef372, -23791573),
45418             new int64(-1521486534, 0x5f1d36f1),
45419             new int64(0x510e527f, -1377402159),
45420             new int64(-1694144372, 0x2b3e6c1f),
45421             new int64(0x1f83d9ab, -79577749),
45422             new int64(0x5be0cd19, 0x137e2179)
45423           ],
45424           T1 = new int64(0, 0),
45425           T2 = new int64(0, 0),
45426           a = new int64(0, 0),
45427           b = new int64(0, 0),
45428           c = new int64(0, 0),
45429           d = new int64(0, 0),
45430           e = new int64(0, 0),
45431           f = new int64(0, 0),
45432           g = new int64(0, 0),
45433           h = new int64(0, 0),
45434           //Temporary variables not specified by the document
45435           s0 = new int64(0, 0),
45436           s1 = new int64(0, 0),
45437           Ch = new int64(0, 0),
45438           Maj = new int64(0, 0),
45439           r1 = new int64(0, 0),
45440           r2 = new int64(0, 0),
45441           r3 = new int64(0, 0);
45442
45443         if (sha512_k === undefined) {
45444           //SHA512 constants
45445           sha512_k = [
45446             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
45447             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
45448             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
45449             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
45450             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
45451             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
45452             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
45453             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
45454             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
45455             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
45456             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
45457             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
45458             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
45459             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
45460             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
45461             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
45462             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
45463             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
45464             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
45465             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
45466             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
45467             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
45468             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
45469             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
45470             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
45471             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
45472             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
45473             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
45474             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
45475             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
45476             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
45477             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
45478             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
45479             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
45480             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
45481             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
45482             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
45483             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
45484             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
45485             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
45486           ];
45487         }
45488
45489         for (i = 0; i < 80; i += 1) {
45490           W[i] = new int64(0, 0);
45491         }
45492
45493         // append padding to the source string. The format is described in the FIPS.
45494         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
45495         x[((len + 128 >> 10) << 5) + 31] = len;
45496         l = x.length;
45497         for (i = 0; i < l; i += 32) { //32 dwords is the block size
45498           int64copy(a, H[0]);
45499           int64copy(b, H[1]);
45500           int64copy(c, H[2]);
45501           int64copy(d, H[3]);
45502           int64copy(e, H[4]);
45503           int64copy(f, H[5]);
45504           int64copy(g, H[6]);
45505           int64copy(h, H[7]);
45506
45507           for (j = 0; j < 16; j += 1) {
45508             W[j].h = x[i + 2 * j];
45509             W[j].l = x[i + 2 * j + 1];
45510           }
45511
45512           for (j = 16; j < 80; j += 1) {
45513             //sigma1
45514             int64rrot(r1, W[j - 2], 19);
45515             int64revrrot(r2, W[j - 2], 29);
45516             int64shr(r3, W[j - 2], 6);
45517             s1.l = r1.l ^ r2.l ^ r3.l;
45518             s1.h = r1.h ^ r2.h ^ r3.h;
45519             //sigma0
45520             int64rrot(r1, W[j - 15], 1);
45521             int64rrot(r2, W[j - 15], 8);
45522             int64shr(r3, W[j - 15], 7);
45523             s0.l = r1.l ^ r2.l ^ r3.l;
45524             s0.h = r1.h ^ r2.h ^ r3.h;
45525
45526             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
45527           }
45528
45529           for (j = 0; j < 80; j += 1) {
45530             //Ch
45531             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45532             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45533
45534             //Sigma1
45535             int64rrot(r1, e, 14);
45536             int64rrot(r2, e, 18);
45537             int64revrrot(r3, e, 9);
45538             s1.l = r1.l ^ r2.l ^ r3.l;
45539             s1.h = r1.h ^ r2.h ^ r3.h;
45540
45541             //Sigma0
45542             int64rrot(r1, a, 28);
45543             int64revrrot(r2, a, 2);
45544             int64revrrot(r3, a, 7);
45545             s0.l = r1.l ^ r2.l ^ r3.l;
45546             s0.h = r1.h ^ r2.h ^ r3.h;
45547
45548             //Maj
45549             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45550             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45551
45552             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45553             int64add(T2, s0, Maj);
45554
45555             int64copy(h, g);
45556             int64copy(g, f);
45557             int64copy(f, e);
45558             int64add(e, d, T1);
45559             int64copy(d, c);
45560             int64copy(c, b);
45561             int64copy(b, a);
45562             int64add(a, T1, T2);
45563           }
45564           int64add(H[0], H[0], a);
45565           int64add(H[1], H[1], b);
45566           int64add(H[2], H[2], c);
45567           int64add(H[3], H[3], d);
45568           int64add(H[4], H[4], e);
45569           int64add(H[5], H[5], f);
45570           int64add(H[6], H[6], g);
45571           int64add(H[7], H[7], h);
45572         }
45573
45574         //represent the hash as an array of 32-bit dwords
45575         for (i = 0; i < 8; i += 1) {
45576           hash[2 * i] = H[i].h;
45577           hash[2 * i + 1] = H[i].l;
45578         }
45579         return hash;
45580       }
45581
45582       //A constructor for 64-bit numbers
45583
45584       function int64(h, l) {
45585         this.h = h;
45586         this.l = l;
45587         //this.toString = int64toString;
45588       }
45589
45590       //Copies src into dst, assuming both are 64-bit numbers
45591
45592       function int64copy(dst, src) {
45593         dst.h = src.h;
45594         dst.l = src.l;
45595       }
45596
45597       //Right-rotates a 64-bit number by shift
45598       //Won't handle cases of shift>=32
45599       //The function revrrot() is for that
45600
45601       function int64rrot(dst, x, shift) {
45602         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45603         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45604       }
45605
45606       //Reverses the dwords of the source and then rotates right by shift.
45607       //This is equivalent to rotation by 32+shift
45608
45609       function int64revrrot(dst, x, shift) {
45610         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45611         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45612       }
45613
45614       //Bitwise-shifts right a 64-bit number by shift
45615       //Won't handle shift>=32, but it's never needed in SHA512
45616
45617       function int64shr(dst, x, shift) {
45618         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45619         dst.h = (x.h >>> shift);
45620       }
45621
45622       //Adds two 64-bit numbers
45623       //Like the original implementation, does not rely on 32-bit operations
45624
45625       function int64add(dst, x, y) {
45626         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45627         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45628         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45629         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45630         dst.l = (w0 & 0xffff) | (w1 << 16);
45631         dst.h = (w2 & 0xffff) | (w3 << 16);
45632       }
45633
45634       //Same, except with 4 addends. Works faster than adding them one by one.
45635
45636       function int64add4(dst, a, b, c, d) {
45637         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45638         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45639         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45640         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45641         dst.l = (w0 & 0xffff) | (w1 << 16);
45642         dst.h = (w2 & 0xffff) | (w3 << 16);
45643       }
45644
45645       //Same, except with 5 addends
45646
45647       function int64add5(dst, a, b, c, d, e) {
45648         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45649           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45650           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45651           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45652         dst.l = (w0 & 0xffff) | (w1 << 16);
45653         dst.h = (w2 & 0xffff) | (w3 << 16);
45654       }
45655     },
45656     /**
45657      * @class Hashes.RMD160
45658      * @constructor
45659      * @param {Object} [config]
45660      *
45661      * A JavaScript implementation of the RIPEMD-160 Algorithm
45662      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45663      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45664      * See http://pajhome.org.uk/crypt/md5 for details.
45665      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45666      */
45667     RMD160: function(options) {
45668       /**
45669        * Private properties configuration variables. You may need to tweak these to be compatible with
45670        * the server-side, but the defaults work in most cases.
45671        * @see this.setUpperCase() method
45672        * @see this.setPad() method
45673        */
45674       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45675         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45676         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45677         /* base-64 pad character. Default '=' for strict RFC compliance   */
45678         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45679         /* enable/disable utf8 encoding */
45680         rmd160_r1 = [
45681           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45682           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45683           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45684           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45685           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45686         ],
45687         rmd160_r2 = [
45688           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45689           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45690           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45691           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45692           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45693         ],
45694         rmd160_s1 = [
45695           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45696           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45697           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45698           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45699           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45700         ],
45701         rmd160_s2 = [
45702           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45703           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45704           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45705           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45706           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45707         ];
45708
45709       /* privileged (public) methods */
45710       this.hex = function(s) {
45711         return rstr2hex(rstr(s, utf8));
45712       };
45713       this.b64 = function(s) {
45714         return rstr2b64(rstr(s, utf8), b64pad);
45715       };
45716       this.any = function(s, e) {
45717         return rstr2any(rstr(s, utf8), e);
45718       };
45719       this.raw = function(s) {
45720         return rstr(s, utf8);
45721       };
45722       this.hex_hmac = function(k, d) {
45723         return rstr2hex(rstr_hmac(k, d));
45724       };
45725       this.b64_hmac = function(k, d) {
45726         return rstr2b64(rstr_hmac(k, d), b64pad);
45727       };
45728       this.any_hmac = function(k, d, e) {
45729         return rstr2any(rstr_hmac(k, d), e);
45730       };
45731       /**
45732        * Perform a simple self-test to see if the VM is working
45733        * @return {String} Hexadecimal hash sample
45734        * @public
45735        */
45736       this.vm_test = function() {
45737         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45738       };
45739       /**
45740        * @description Enable/disable uppercase hexadecimal returned string
45741        * @param {boolean}
45742        * @return {Object} this
45743        * @public
45744        */
45745       this.setUpperCase = function(a) {
45746         if (typeof a === 'boolean') {
45747           hexcase = a;
45748         }
45749         return this;
45750       };
45751       /**
45752        * @description Defines a base64 pad string
45753        * @param {string} Pad
45754        * @return {Object} this
45755        * @public
45756        */
45757       this.setPad = function(a) {
45758         if (typeof a !== 'undefined') {
45759           b64pad = a;
45760         }
45761         return this;
45762       };
45763       /**
45764        * @description Defines a base64 pad string
45765        * @param {boolean}
45766        * @return {Object} this
45767        * @public
45768        */
45769       this.setUTF8 = function(a) {
45770         if (typeof a === 'boolean') {
45771           utf8 = a;
45772         }
45773         return this;
45774       };
45775
45776       /* private methods */
45777
45778       /**
45779        * Calculate the rmd160 of a raw string
45780        */
45781
45782       function rstr(s) {
45783         s = (utf8) ? utf8Encode(s) : s;
45784         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45785       }
45786
45787       /**
45788        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45789        */
45790
45791       function rstr_hmac(key, data) {
45792         key = (utf8) ? utf8Encode(key) : key;
45793         data = (utf8) ? utf8Encode(data) : data;
45794         var i, hash,
45795           bkey = rstr2binl(key),
45796           ipad = Array(16),
45797           opad = Array(16);
45798
45799         if (bkey.length > 16) {
45800           bkey = binl(bkey, key.length * 8);
45801         }
45802
45803         for (i = 0; i < 16; i += 1) {
45804           ipad[i] = bkey[i] ^ 0x36363636;
45805           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45806         }
45807         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45808         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45809       }
45810
45811       /**
45812        * Convert an array of little-endian words to a string
45813        */
45814
45815       function binl2rstr(input) {
45816         var i, output = '',
45817           l = input.length * 32;
45818         for (i = 0; i < l; i += 8) {
45819           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45820         }
45821         return output;
45822       }
45823
45824       /**
45825        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45826        */
45827
45828       function binl(x, len) {
45829         var T, j, i, l,
45830           h0 = 0x67452301,
45831           h1 = 0xefcdab89,
45832           h2 = 0x98badcfe,
45833           h3 = 0x10325476,
45834           h4 = 0xc3d2e1f0,
45835           A1, B1, C1, D1, E1,
45836           A2, B2, C2, D2, E2;
45837
45838         /* append padding */
45839         x[len >> 5] |= 0x80 << (len % 32);
45840         x[(((len + 64) >>> 9) << 4) + 14] = len;
45841         l = x.length;
45842
45843         for (i = 0; i < l; i += 16) {
45844           A1 = A2 = h0;
45845           B1 = B2 = h1;
45846           C1 = C2 = h2;
45847           D1 = D2 = h3;
45848           E1 = E2 = h4;
45849           for (j = 0; j <= 79; j += 1) {
45850             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45851             T = safe_add(T, x[i + rmd160_r1[j]]);
45852             T = safe_add(T, rmd160_K1(j));
45853             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45854             A1 = E1;
45855             E1 = D1;
45856             D1 = bit_rol(C1, 10);
45857             C1 = B1;
45858             B1 = T;
45859             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45860             T = safe_add(T, x[i + rmd160_r2[j]]);
45861             T = safe_add(T, rmd160_K2(j));
45862             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45863             A2 = E2;
45864             E2 = D2;
45865             D2 = bit_rol(C2, 10);
45866             C2 = B2;
45867             B2 = T;
45868           }
45869
45870           T = safe_add(h1, safe_add(C1, D2));
45871           h1 = safe_add(h2, safe_add(D1, E2));
45872           h2 = safe_add(h3, safe_add(E1, A2));
45873           h3 = safe_add(h4, safe_add(A1, B2));
45874           h4 = safe_add(h0, safe_add(B1, C2));
45875           h0 = T;
45876         }
45877         return [h0, h1, h2, h3, h4];
45878       }
45879
45880       // specific algorithm methods
45881
45882       function rmd160_f(j, x, y, z) {
45883         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45884           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45885           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45886           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45887           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45888           'rmd160_f: j out of range';
45889       }
45890
45891       function rmd160_K1(j) {
45892         return (0 <= j && j <= 15) ? 0x00000000 :
45893           (16 <= j && j <= 31) ? 0x5a827999 :
45894           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45895           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45896           (64 <= j && j <= 79) ? 0xa953fd4e :
45897           'rmd160_K1: j out of range';
45898       }
45899
45900       function rmd160_K2(j) {
45901         return (0 <= j && j <= 15) ? 0x50a28be6 :
45902           (16 <= j && j <= 31) ? 0x5c4dd124 :
45903           (32 <= j && j <= 47) ? 0x6d703ef3 :
45904           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45905           (64 <= j && j <= 79) ? 0x00000000 :
45906           'rmd160_K2: j out of range';
45907       }
45908     }
45909   };
45910
45911   // exposes Hashes
45912   (function(window, undefined) {
45913     var freeExports = false;
45914     {
45915       freeExports = exports;
45916       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45917         window = commonjsGlobal;
45918       }
45919     }
45920
45921     if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
45922       // define as an anonymous module, so, through path mapping, it can be aliased
45923       undefined(function() {
45924         return Hashes;
45925       });
45926     } else if (freeExports) {
45927       // in Node.js or RingoJS v0.8.0+
45928       if ('object' === 'object' && module && module.exports === freeExports) {
45929         module.exports = Hashes;
45930       }
45931       // in Narwhal or RingoJS v0.7.0-
45932       else {
45933         freeExports.Hashes = Hashes;
45934       }
45935     } else {
45936       // in a browser or Rhino
45937       window.Hashes = Hashes;
45938     }
45939   }(this));
45940 }()); // IIFE
45941 });
45942
45943 var immutable = extend$2;
45944
45945 var hasOwnProperty = Object.prototype.hasOwnProperty;
45946
45947 function extend$2() {
45948     var target = {};
45949
45950     for (var i = 0; i < arguments.length; i++) {
45951         var source = arguments[i];
45952
45953         for (var key in source) {
45954             if (hasOwnProperty.call(source, key)) {
45955                 target[key] = source[key];
45956             }
45957         }
45958     }
45959
45960     return target
45961 }
45962
45963 var hashes = hashes$1;
45964 var xtend$1 = immutable;
45965 var sha1 = new hashes.SHA1();
45966
45967 var ohauth$1 = {};
45968
45969 ohauth$1.qsString = function(obj) {
45970     return Object.keys(obj).sort().map(function(key) {
45971         return ohauth$1.percentEncode(key) + '=' +
45972             ohauth$1.percentEncode(obj[key]);
45973     }).join('&');
45974 };
45975
45976 ohauth$1.stringQs = function(str) {
45977     return str.split('&').filter(function (pair) {
45978         return pair !== '';
45979     }).reduce(function(obj, pair){
45980         var parts = pair.split('=');
45981         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45982             '' : decodeURIComponent(parts[1]);
45983         return obj;
45984     }, {});
45985 };
45986
45987 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45988     var xhr = new XMLHttpRequest(),
45989         twoHundred = /^20\d$/;
45990     xhr.onreadystatechange = function() {
45991         if (4 === xhr.readyState && 0 !== xhr.status) {
45992             if (twoHundred.test(xhr.status)) callback(null, xhr);
45993             else return callback(xhr, null);
45994         }
45995     };
45996     xhr.onerror = function(e) { return callback(e, null); };
45997     xhr.open(method, url, true);
45998     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45999     xhr.send(data);
46000     return xhr;
46001 };
46002
46003 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
46004     var headers = (options && options.header) || {
46005         'Content-Type': 'application/x-www-form-urlencoded'
46006     };
46007     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
46008     return ohauth$1.rawxhr(method, url, data, headers, callback);
46009 };
46010
46011 ohauth$1.nonce = function() {
46012     for (var o = ''; o.length < 6;) {
46013         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
46014     }
46015     return o;
46016 };
46017
46018 ohauth$1.authHeader = function(obj) {
46019     return Object.keys(obj).sort().map(function(key) {
46020         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
46021     }).join(', ');
46022 };
46023
46024 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
46025
46026 ohauth$1.percentEncode = function(s) {
46027     return encodeURIComponent(s)
46028         .replace(/\!/g, '%21').replace(/\'/g, '%27')
46029         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
46030 };
46031
46032 ohauth$1.baseString = function(method, url, params) {
46033     if (params.oauth_signature) delete params.oauth_signature;
46034     return [
46035         method,
46036         ohauth$1.percentEncode(url),
46037         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
46038 };
46039
46040 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
46041     return sha1.b64_hmac(
46042         ohauth$1.percentEncode(oauth_secret) + '&' +
46043         ohauth$1.percentEncode(token_secret),
46044         baseString);
46045 };
46046
46047 /**
46048  * Takes an options object for configuration (consumer_key,
46049  * consumer_secret, version, signature_method, token, token_secret)
46050  * and returns a function that generates the Authorization header
46051  * for given data.
46052  *
46053  * The returned function takes these parameters:
46054  * - method: GET/POST/...
46055  * - uri: full URI with protocol, port, path and query string
46056  * - extra_params: any extra parameters (that are passed in the POST data),
46057  *   can be an object or a from-urlencoded string.
46058  *
46059  * Returned function returns full OAuth header with "OAuth" string in it.
46060  */
46061
46062 ohauth$1.headerGenerator = function(options) {
46063     options = options || {};
46064     var consumer_key = options.consumer_key || '',
46065         consumer_secret = options.consumer_secret || '',
46066         signature_method = options.signature_method || 'HMAC-SHA1',
46067         version = options.version || '1.0',
46068         token = options.token || '',
46069         token_secret = options.token_secret || '';
46070
46071     return function(method, uri, extra_params) {
46072         method = method.toUpperCase();
46073         if (typeof extra_params === 'string' && extra_params.length > 0) {
46074             extra_params = ohauth$1.stringQs(extra_params);
46075         }
46076
46077         var uri_parts = uri.split('?', 2),
46078         base_uri = uri_parts[0];
46079
46080         var query_params = uri_parts.length === 2 ?
46081             ohauth$1.stringQs(uri_parts[1]) : {};
46082
46083         var oauth_params = {
46084             oauth_consumer_key: consumer_key,
46085             oauth_signature_method: signature_method,
46086             oauth_version: version,
46087             oauth_timestamp: ohauth$1.timestamp(),
46088             oauth_nonce: ohauth$1.nonce()
46089         };
46090
46091         if (token) oauth_params.oauth_token = token;
46092
46093         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
46094             base_str = ohauth$1.baseString(method, base_uri, all_params);
46095
46096         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
46097
46098         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
46099     };
46100 };
46101
46102 var index$13 = ohauth$1;
46103
46104 var store$1 = createCommonjsModule(function (module, exports) {
46105 "use strict"
46106 // Module export pattern from
46107 // https://github.com/umdjs/umd/blob/master/returnExports.js
46108 ;(function (root, factory) {
46109     if (typeof undefined === 'function' && undefined.amd) {
46110         // AMD. Register as an anonymous module.
46111         undefined([], factory);
46112     } else {
46113         // Node. Does not work with strict CommonJS, but
46114         // only CommonJS-like environments that support module.exports,
46115         // like Node.
46116         module.exports = factory();
46117     }
46118 }(commonjsGlobal, function () {
46119         
46120         // Store.js
46121         var store = {},
46122                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
46123                 doc = win.document,
46124                 localStorageName = 'localStorage',
46125                 scriptTag = 'script',
46126                 storage;
46127
46128         store.disabled = false;
46129         store.version = '1.3.20';
46130         store.set = function(key, value) {};
46131         store.get = function(key, defaultVal) {};
46132         store.has = function(key) { return store.get(key) !== undefined };
46133         store.remove = function(key) {};
46134         store.clear = function() {};
46135         store.transact = function(key, defaultVal, transactionFn) {
46136                 if (transactionFn == null) {
46137                         transactionFn = defaultVal;
46138                         defaultVal = null;
46139                 }
46140                 if (defaultVal == null) {
46141                         defaultVal = {};
46142                 }
46143                 var val = store.get(key, defaultVal);
46144                 transactionFn(val);
46145                 store.set(key, val);
46146         };
46147         store.getAll = function() {};
46148         store.forEach = function() {};
46149
46150         store.serialize = function(value) {
46151                 return JSON.stringify(value)
46152         };
46153         store.deserialize = function(value) {
46154                 if (typeof value != 'string') { return undefined }
46155                 try { return JSON.parse(value) }
46156                 catch(e) { return value || undefined }
46157         };
46158
46159         // Functions to encapsulate questionable FireFox 3.6.13 behavior
46160         // when about.config::dom.storage.enabled === false
46161         // See https://github.com/marcuswestin/store.js/issues#issue/13
46162         function isLocalStorageNameSupported() {
46163                 try { return (localStorageName in win && win[localStorageName]) }
46164                 catch(err) { return false }
46165         }
46166
46167         if (isLocalStorageNameSupported()) {
46168                 storage = win[localStorageName];
46169                 store.set = function(key, val) {
46170                         if (val === undefined) { return store.remove(key) }
46171                         storage.setItem(key, store.serialize(val));
46172                         return val
46173                 };
46174                 store.get = function(key, defaultVal) {
46175                         var val = store.deserialize(storage.getItem(key));
46176                         return (val === undefined ? defaultVal : val)
46177                 };
46178                 store.remove = function(key) { storage.removeItem(key); };
46179                 store.clear = function() { storage.clear(); };
46180                 store.getAll = function() {
46181                         var ret = {};
46182                         store.forEach(function(key, val) {
46183                                 ret[key] = val;
46184                         });
46185                         return ret
46186                 };
46187                 store.forEach = function(callback) {
46188                         for (var i=0; i<storage.length; i++) {
46189                                 var key = storage.key(i);
46190                                 callback(key, store.get(key));
46191                         }
46192                 };
46193         } else if (doc && doc.documentElement.addBehavior) {
46194                 var storageOwner,
46195                         storageContainer;
46196                 // Since #userData storage applies only to specific paths, we need to
46197                 // somehow link our data to a specific path.  We choose /favicon.ico
46198                 // as a pretty safe option, since all browsers already make a request to
46199                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
46200                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
46201                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
46202                 // since the iframe access rules appear to allow direct access and
46203                 // manipulation of the document element, even for a 404 page.  This
46204                 // document can be used instead of the current document (which would
46205                 // have been limited to the current path) to perform #userData storage.
46206                 try {
46207                         storageContainer = new ActiveXObject('htmlfile');
46208                         storageContainer.open();
46209                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
46210                         storageContainer.close();
46211                         storageOwner = storageContainer.w.frames[0].document;
46212                         storage = storageOwner.createElement('div');
46213                 } catch(e) {
46214                         // somehow ActiveXObject instantiation failed (perhaps some special
46215                         // security settings or otherwse), fall back to per-path storage
46216                         storage = doc.createElement('div');
46217                         storageOwner = doc.body;
46218                 }
46219                 var withIEStorage = function(storeFunction) {
46220                         return function() {
46221                                 var args = Array.prototype.slice.call(arguments, 0);
46222                                 args.unshift(storage);
46223                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
46224                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
46225                                 storageOwner.appendChild(storage);
46226                                 storage.addBehavior('#default#userData');
46227                                 storage.load(localStorageName);
46228                                 var result = storeFunction.apply(store, args);
46229                                 storageOwner.removeChild(storage);
46230                                 return result
46231                         }
46232                 };
46233
46234                 // In IE7, keys cannot start with a digit or contain certain chars.
46235                 // See https://github.com/marcuswestin/store.js/issues/40
46236                 // See https://github.com/marcuswestin/store.js/issues/83
46237                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
46238                 var ieKeyFix = function(key) {
46239                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
46240                 };
46241                 store.set = withIEStorage(function(storage, key, val) {
46242                         key = ieKeyFix(key);
46243                         if (val === undefined) { return store.remove(key) }
46244                         storage.setAttribute(key, store.serialize(val));
46245                         storage.save(localStorageName);
46246                         return val
46247                 });
46248                 store.get = withIEStorage(function(storage, key, defaultVal) {
46249                         key = ieKeyFix(key);
46250                         var val = store.deserialize(storage.getAttribute(key));
46251                         return (val === undefined ? defaultVal : val)
46252                 });
46253                 store.remove = withIEStorage(function(storage, key) {
46254                         key = ieKeyFix(key);
46255                         storage.removeAttribute(key);
46256                         storage.save(localStorageName);
46257                 });
46258                 store.clear = withIEStorage(function(storage) {
46259                         var attributes = storage.XMLDocument.documentElement.attributes;
46260                         storage.load(localStorageName);
46261                         for (var i=attributes.length-1; i>=0; i--) {
46262                                 storage.removeAttribute(attributes[i].name);
46263                         }
46264                         storage.save(localStorageName);
46265                 });
46266                 store.getAll = function(storage) {
46267                         var ret = {};
46268                         store.forEach(function(key, val) {
46269                                 ret[key] = val;
46270                         });
46271                         return ret
46272                 };
46273                 store.forEach = withIEStorage(function(storage, callback) {
46274                         var attributes = storage.XMLDocument.documentElement.attributes;
46275                         for (var i=0, attr; attr=attributes[i]; ++i) {
46276                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
46277                         }
46278                 });
46279         }
46280
46281         try {
46282                 var testKey = '__storejs__';
46283                 store.set(testKey, testKey);
46284                 if (store.get(testKey) != testKey) { store.disabled = true; }
46285                 store.remove(testKey);
46286         } catch(e) {
46287                 store.disabled = true;
46288         }
46289         store.enabled = !store.disabled;
46290         
46291         return store
46292 }));
46293 });
46294
46295 var ohauth = index$13;
46296 var xtend = immutable;
46297 var store = store$1;
46298
46299 // # osm-auth
46300 //
46301 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
46302 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
46303 // does not support custom headers, which this uses everywhere.
46304 var index$12 = function(o) {
46305
46306     var oauth = {};
46307
46308     // authenticated users will also have a request token secret, but it's
46309     // not used in transactions with the server
46310     oauth.authenticated = function() {
46311         return !!(token('oauth_token') && token('oauth_token_secret'));
46312     };
46313
46314     oauth.logout = function() {
46315         token('oauth_token', '');
46316         token('oauth_token_secret', '');
46317         token('oauth_request_token_secret', '');
46318         return oauth;
46319     };
46320
46321     // TODO: detect lack of click event
46322     oauth.authenticate = function(callback) {
46323         if (oauth.authenticated()) return callback();
46324
46325         oauth.logout();
46326
46327         // ## Getting a request token
46328         var params = timenonce(getAuth(o)),
46329             url = o.url + '/oauth/request_token';
46330
46331         params.oauth_signature = ohauth.signature(
46332             o.oauth_secret, '',
46333             ohauth.baseString('POST', url, params));
46334
46335         if (!o.singlepage) {
46336             // Create a 600x550 popup window in the center of the screen
46337             var w = 600, h = 550,
46338                 settings = [
46339                     ['width', w], ['height', h],
46340                     ['left', screen.width / 2 - w / 2],
46341                     ['top', screen.height / 2 - h / 2]].map(function(x) {
46342                         return x.join('=');
46343                     }).join(','),
46344                 popup = window.open('about:blank', 'oauth_window', settings);
46345         }
46346
46347         // Request a request token. When this is complete, the popup
46348         // window is redirected to OSM's authorization page.
46349         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
46350         o.loading();
46351
46352         function reqTokenDone(err, xhr) {
46353             o.done();
46354             if (err) return callback(err);
46355             var resp = ohauth.stringQs(xhr.response);
46356             token('oauth_request_token_secret', resp.oauth_token_secret);
46357             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
46358                 oauth_token: resp.oauth_token,
46359                 oauth_callback: location.href.replace('index.html', '')
46360                     .replace(/#.*/, '').replace(location.search, '') + o.landing
46361             });
46362
46363             if (o.singlepage) {
46364                 location.href = authorize_url;
46365             } else {
46366                 popup.location = authorize_url;
46367             }
46368         }
46369
46370         // Called by a function in a landing page, in the popup window. The
46371         // window closes itself.
46372         window.authComplete = function(token) {
46373             var oauth_token = ohauth.stringQs(token.split('?')[1]);
46374             get_access_token(oauth_token.oauth_token);
46375             delete window.authComplete;
46376         };
46377
46378         // ## Getting an request token
46379         //
46380         // At this point we have an `oauth_token`, brought in from a function
46381         // call on a landing page popup.
46382         function get_access_token(oauth_token) {
46383             var url = o.url + '/oauth/access_token',
46384                 params = timenonce(getAuth(o)),
46385                 request_token_secret = token('oauth_request_token_secret');
46386             params.oauth_token = oauth_token;
46387             params.oauth_signature = ohauth.signature(
46388                 o.oauth_secret,
46389                 request_token_secret,
46390                 ohauth.baseString('POST', url, params));
46391
46392             // ## Getting an access token
46393             //
46394             // The final token required for authentication. At this point
46395             // we have a `request token secret`
46396             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46397             o.loading();
46398         }
46399
46400         function accessTokenDone(err, xhr) {
46401             o.done();
46402             if (err) return callback(err);
46403             var access_token = ohauth.stringQs(xhr.response);
46404             token('oauth_token', access_token.oauth_token);
46405             token('oauth_token_secret', access_token.oauth_token_secret);
46406             callback(null, oauth);
46407         }
46408     };
46409
46410     oauth.bootstrapToken = function(oauth_token, callback) {
46411         // ## Getting an request token
46412         // At this point we have an `oauth_token`, brought in from a function
46413         // call on a landing page popup.
46414         function get_access_token(oauth_token) {
46415             var url = o.url + '/oauth/access_token',
46416                 params = timenonce(getAuth(o)),
46417                 request_token_secret = token('oauth_request_token_secret');
46418             params.oauth_token = oauth_token;
46419             params.oauth_signature = ohauth.signature(
46420                 o.oauth_secret,
46421                 request_token_secret,
46422                 ohauth.baseString('POST', url, params));
46423
46424             // ## Getting an access token
46425             // The final token required for authentication. At this point
46426             // we have a `request token secret`
46427             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46428             o.loading();
46429         }
46430
46431         function accessTokenDone(err, xhr) {
46432             o.done();
46433             if (err) return callback(err);
46434             var access_token = ohauth.stringQs(xhr.response);
46435             token('oauth_token', access_token.oauth_token);
46436             token('oauth_token_secret', access_token.oauth_token_secret);
46437             callback(null, oauth);
46438         }
46439
46440         get_access_token(oauth_token);
46441     };
46442
46443     // # xhr
46444     //
46445     // A single XMLHttpRequest wrapper that does authenticated calls if the
46446     // user has logged in.
46447     oauth.xhr = function(options, callback) {
46448         if (!oauth.authenticated()) {
46449             if (o.auto) {
46450                 return oauth.authenticate(run);
46451             } else {
46452                 callback('not authenticated', null);
46453                 return;
46454             }
46455         } else {
46456             return run();
46457         }
46458
46459         function run() {
46460             var params = timenonce(getAuth(o)),
46461                 oauth_token_secret = token('oauth_token_secret'),
46462                 url = (options.prefix !== false) ? o.url + options.path : options.path,
46463                 url_parts = url.replace(/#.*$/, '').split('?', 2),
46464                 base_url = url_parts[0],
46465                 query = (url_parts.length === 2) ? url_parts[1] : '';
46466
46467             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
46468             if ((!options.options || !options.options.header ||
46469                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
46470                 options.content) {
46471                 params = xtend(params, ohauth.stringQs(options.content));
46472             }
46473
46474             params.oauth_token = token('oauth_token');
46475             params.oauth_signature = ohauth.signature(
46476                 o.oauth_secret,
46477                 oauth_token_secret,
46478                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
46479             );
46480
46481             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
46482         }
46483
46484         function done(err, xhr) {
46485             if (err) return callback(err);
46486             else if (xhr.responseXML) return callback(err, xhr.responseXML);
46487             else return callback(err, xhr.response);
46488         }
46489     };
46490
46491     // pre-authorize this object, if we can just get a token and token_secret
46492     // from the start
46493     oauth.preauth = function(c) {
46494         if (!c) return;
46495         if (c.oauth_token) token('oauth_token', c.oauth_token);
46496         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
46497         return oauth;
46498     };
46499
46500     oauth.options = function(_) {
46501         if (!arguments.length) return o;
46502
46503         o = _;
46504         o.url = o.url || 'http://www.openstreetmap.org';
46505         o.landing = o.landing || 'land.html';
46506         o.singlepage = o.singlepage || false;
46507
46508         // Optional loading and loading-done functions for nice UI feedback.
46509         // by default, no-ops
46510         o.loading = o.loading || function() {};
46511         o.done = o.done || function() {};
46512
46513         return oauth.preauth(o);
46514     };
46515
46516     // 'stamp' an authentication object from `getAuth()`
46517     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
46518     // and timestamp
46519     function timenonce(o) {
46520         o.oauth_timestamp = ohauth.timestamp();
46521         o.oauth_nonce = ohauth.nonce();
46522         return o;
46523     }
46524
46525     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46526     // can be used with multiple APIs and the keys in `localStorage`
46527     // will not clash
46528     var token;
46529
46530     if (store.enabled) {
46531         token = function (x, y) {
46532             if (arguments.length === 1) return store.get(o.url + x);
46533             else if (arguments.length === 2) return store.set(o.url + x, y);
46534         };
46535     } else {
46536         var storage = {};
46537         token = function (x, y) {
46538             if (arguments.length === 1) return storage[o.url + x];
46539             else if (arguments.length === 2) return storage[o.url + x] = y;
46540         };
46541     }
46542
46543     // Get an authentication object. If you just add and remove properties
46544     // from a single object, you'll need to use `delete` to make sure that
46545     // it doesn't contain undesired properties for authentication
46546     function getAuth(o) {
46547         return {
46548             oauth_consumer_key: o.oauth_consumer_key,
46549             oauth_signature_method: 'HMAC-SHA1'
46550         };
46551     }
46552
46553     // potentially pre-authorize
46554     oauth.options(o);
46555
46556     return oauth;
46557 };
46558
46559 var JXON = new (function () {
46560   var
46561     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46562     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46563
46564   function parseText (sValue) {
46565     if (rIsNull.test(sValue)) { return null; }
46566     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46567     if (isFinite(sValue)) { return parseFloat(sValue); }
46568     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46569     return sValue;
46570   }
46571
46572   function EmptyTree () { }
46573   EmptyTree.prototype.toString = function () { return 'null'; };
46574   EmptyTree.prototype.valueOf = function () { return null; };
46575
46576   function objectify (vValue) {
46577     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46578   }
46579
46580   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46581     var
46582       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46583       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46584
46585     var
46586       sProp, vContent, nLength = 0, sCollectedTxt = '',
46587       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46588
46589     if (bChildren) {
46590       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46591         oNode = oParentNode.childNodes.item(nItem);
46592         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46593         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46594         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46595       }
46596     }
46597
46598     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46599
46600     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46601
46602     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46603       sProp = aCache[nElId].nodeName.toLowerCase();
46604       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46605       if (vResult.hasOwnProperty(sProp)) {
46606         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46607         vResult[sProp].push(vContent);
46608       } else {
46609         vResult[sProp] = vContent;
46610         nLength++;
46611       }
46612     }
46613
46614     if (bAttributes) {
46615       var
46616         nAttrLen = oParentNode.attributes.length,
46617         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46618
46619       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46620         oAttrib = oParentNode.attributes.item(nAttrib);
46621         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46622       }
46623
46624       if (bNesteAttr) {
46625         if (bFreeze) { Object.freeze(oAttrParent); }
46626         vResult[sAttributesProp] = oAttrParent;
46627         nLength -= nAttrLen - 1;
46628       }
46629     }
46630
46631     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46632       vResult[sValueProp] = vBuiltVal;
46633     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46634       vResult = vBuiltVal;
46635     }
46636
46637     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46638
46639     aCache.length = nLevelStart;
46640
46641     return vResult;
46642   }
46643
46644   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46645     var vValue, oChild;
46646
46647     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46648       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46649     } else if (oParentObj.constructor === Date) {
46650       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46651     }
46652
46653     for (var sName in oParentObj) {
46654       vValue = oParentObj[sName];
46655       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46656       if (sName === sValueProp) {
46657         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46658       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46659         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46660       } else if (sName.charAt(0) === sAttrPref) {
46661         oParentEl.setAttribute(sName.slice(1), vValue);
46662       } else if (vValue.constructor === Array) {
46663         for (var nItem = 0; nItem < vValue.length; nItem++) {
46664           oChild = oXMLDoc.createElement(sName);
46665           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46666           oParentEl.appendChild(oChild);
46667         }
46668       } else {
46669         oChild = oXMLDoc.createElement(sName);
46670         if (vValue instanceof Object) {
46671           loadObjTree(oXMLDoc, oChild, vValue);
46672         } else if (vValue !== null && vValue !== true) {
46673           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46674         }
46675         oParentEl.appendChild(oChild);
46676      }
46677    }
46678   }
46679
46680   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46681     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46682     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46683   };
46684
46685   this.unbuild = function (oObjTree) {    
46686     var oNewDoc = document.implementation.createDocument('', '', null);
46687     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46688     return oNewDoc;
46689   };
46690
46691   this.stringify = function (oObjTree) {
46692     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46693   };
46694 })();
46695
46696 // var myObject = JXON.build(doc);
46697 // we got our javascript object! try: alert(JSON.stringify(myObject));
46698
46699 // var newDoc = JXON.unbuild(myObject);
46700 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46701
46702 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46703 var useHttps = window.location.protocol === 'https:';
46704 var protocol = useHttps ? 'https:' : 'http:';
46705 var urlroot = protocol + '//www.openstreetmap.org';
46706 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46707 var inflight = {};
46708 var loadedTiles = {};
46709 var tileZoom$1 = 16;
46710 var oauth = index$12({
46711         url: urlroot,
46712         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46713         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46714         loading: authLoading,
46715         done: authDone
46716     });
46717 var rateLimitError;
46718 var userChangesets;
46719 var userDetails;
46720 var off;
46721
46722
46723 function authLoading() {
46724     dispatch$3.call('authLoading');
46725 }
46726
46727
46728 function authDone() {
46729     dispatch$3.call('authDone');
46730 }
46731
46732
46733 function abortRequest$1(i) {
46734     if (i) {
46735         i.abort();
46736     }
46737 }
46738
46739
46740 function getLoc(attrs) {
46741     var lon = attrs.lon && attrs.lon.value,
46742         lat = attrs.lat && attrs.lat.value;
46743     return [parseFloat(lon), parseFloat(lat)];
46744 }
46745
46746
46747 function getNodes(obj) {
46748     var elems = obj.getElementsByTagName('nd'),
46749         nodes = new Array(elems.length);
46750     for (var i = 0, l = elems.length; i < l; i++) {
46751         nodes[i] = 'n' + elems[i].attributes.ref.value;
46752     }
46753     return nodes;
46754 }
46755
46756
46757 function getTags(obj) {
46758     var elems = obj.getElementsByTagName('tag'),
46759         tags = {};
46760     for (var i = 0, l = elems.length; i < l; i++) {
46761         var attrs = elems[i].attributes;
46762         tags[attrs.k.value] = attrs.v.value;
46763     }
46764
46765     return tags;
46766 }
46767
46768
46769 function getMembers(obj) {
46770     var elems = obj.getElementsByTagName('member'),
46771         members = new Array(elems.length);
46772     for (var i = 0, l = elems.length; i < l; i++) {
46773         var attrs = elems[i].attributes;
46774         members[i] = {
46775             id: attrs.type.value[0] + attrs.ref.value,
46776             type: attrs.type.value,
46777             role: attrs.role.value
46778         };
46779     }
46780     return members;
46781 }
46782
46783
46784 function getVisible(attrs) {
46785     return (!attrs.visible || attrs.visible.value !== 'false');
46786 }
46787
46788
46789 var parsers = {
46790     node: function nodeData(obj) {
46791         var attrs = obj.attributes;
46792         return new osmNode({
46793             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46794             loc: getLoc(attrs),
46795             version: attrs.version.value,
46796             user: attrs.user && attrs.user.value,
46797             tags: getTags(obj),
46798             visible: getVisible(attrs)
46799         });
46800     },
46801
46802     way: function wayData(obj) {
46803         var attrs = obj.attributes;
46804         return new osmWay({
46805             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46806             version: attrs.version.value,
46807             user: attrs.user && attrs.user.value,
46808             tags: getTags(obj),
46809             nodes: getNodes(obj),
46810             visible: getVisible(attrs)
46811         });
46812     },
46813
46814     relation: function relationData(obj) {
46815         var attrs = obj.attributes;
46816         return new osmRelation({
46817             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46818             version: attrs.version.value,
46819             user: attrs.user && attrs.user.value,
46820             tags: getTags(obj),
46821             members: getMembers(obj),
46822             visible: getVisible(attrs)
46823         });
46824     }
46825 };
46826
46827
46828 function parse(xml$$1) {
46829     if (!xml$$1 || !xml$$1.childNodes) return;
46830
46831     var root = xml$$1.childNodes[0],
46832         children = root.childNodes,
46833         entities = [];
46834
46835     for (var i = 0, l = children.length; i < l; i++) {
46836         var child = children[i],
46837             parser = parsers[child.nodeName];
46838         if (parser) {
46839             entities.push(parser(child));
46840         }
46841     }
46842
46843     return entities;
46844 }
46845
46846
46847 var serviceOsm = {
46848
46849     init: function() {
46850         utilRebind(this, dispatch$3, 'on');
46851     },
46852
46853
46854     reset: function() {
46855         userChangesets = undefined;
46856         userDetails = undefined;
46857         rateLimitError = undefined;
46858         lodash.forEach(inflight, abortRequest$1);
46859         loadedTiles = {};
46860         inflight = {};
46861         return this;
46862     },
46863
46864
46865     changesetURL: function(changesetId) {
46866         return urlroot + '/changeset/' + changesetId;
46867     },
46868
46869
46870     changesetsURL: function(center, zoom$$1) {
46871         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46872         return urlroot + '/history#map=' +
46873             Math.floor(zoom$$1) + '/' +
46874             center[1].toFixed(precision) + '/' +
46875             center[0].toFixed(precision);
46876     },
46877
46878
46879     entityURL: function(entity) {
46880         return urlroot + '/' + entity.type + '/' + entity.osmId();
46881     },
46882
46883
46884     userURL: function(username) {
46885         return urlroot + '/user/' + username;
46886     },
46887
46888
46889     loadFromAPI: function(path$$1, callback) {
46890         var that = this;
46891
46892         function done(err, xml$$1) {
46893             var isAuthenticated = that.authenticated();
46894
46895             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46896             // Logout and retry the request..
46897             if (isAuthenticated && err &&
46898                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46899                 that.logout();
46900                 that.loadFromAPI(path$$1, callback);
46901
46902             // else, no retry..
46903             } else {
46904                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46905                 // Set the rateLimitError flag and trigger a warning..
46906                 if (!isAuthenticated && !rateLimitError && err &&
46907                         (err.status === 509 || err.status === 429)) {
46908                     rateLimitError = err;
46909                     dispatch$3.call('change');
46910                 }
46911
46912                 if (callback) {
46913                     callback(err, parse(xml$$1));
46914                 }
46915             }
46916         }
46917
46918         if (this.authenticated()) {
46919             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46920         } else {
46921             var url = urlroot + path$$1;
46922             return xml(url).get(done);
46923         }
46924     },
46925
46926
46927     loadEntity: function(id, callback) {
46928         var type = osmEntity$$1.id.type(id),
46929             osmID = osmEntity$$1.id.toOSM(id);
46930
46931         this.loadFromAPI(
46932             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46933             function(err, entities) {
46934                 if (callback) callback(err, { data: entities });
46935             }
46936         );
46937     },
46938
46939
46940     loadEntityVersion: function(id, version$$1, callback) {
46941         var type = osmEntity$$1.id.type(id),
46942             osmID = osmEntity$$1.id.toOSM(id);
46943
46944         this.loadFromAPI(
46945             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46946             function(err, entities) {
46947                 if (callback) callback(err, { data: entities });
46948             }
46949         );
46950     },
46951
46952
46953     loadMultiple: function(ids, callback) {
46954         var that = this;
46955         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46956             var type = k + 's',
46957                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46958
46959             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46960                 that.loadFromAPI(
46961                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46962                     function(err, entities) {
46963                         if (callback) callback(err, { data: entities });
46964                     }
46965                 );
46966             });
46967         });
46968     },
46969
46970
46971     authenticated: function() {
46972         return oauth.authenticated();
46973     },
46974
46975
46976     // Generate Changeset XML. Returns a string.
46977     changesetJXON: function(tags) {
46978         return {
46979             osm: {
46980                 changeset: {
46981                     tag: lodash.map(tags, function(value, key) {
46982                         return { '@k': key, '@v': value };
46983                     }),
46984                     '@version': 0.6,
46985                     '@generator': 'iD'
46986                 }
46987             }
46988         };
46989     },
46990
46991
46992     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46993     // XML. Returns a string.
46994     osmChangeJXON: function(changeset_id, changes) {
46995         function nest$$1(x, order) {
46996             var groups = {};
46997             for (var i = 0; i < x.length; i++) {
46998                 var tagName = Object.keys(x[i])[0];
46999                 if (!groups[tagName]) groups[tagName] = [];
47000                 groups[tagName].push(x[i][tagName]);
47001             }
47002             var ordered = {};
47003             order.forEach(function(o) {
47004                 if (groups[o]) ordered[o] = groups[o];
47005             });
47006             return ordered;
47007         }
47008
47009         function rep(entity) {
47010             return entity.asJXON(changeset_id);
47011         }
47012
47013         return {
47014             osmChange: {
47015                 '@version': 0.6,
47016                 '@generator': 'iD',
47017                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
47018                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
47019                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
47020             }
47021         };
47022     },
47023
47024
47025     changesetTags: function(version$$1, comment, imageryUsed) {
47026         var detected = utilDetect(),
47027             tags = {
47028                 created_by: ('iD ' + version$$1).substr(0, 255),
47029                 imagery_used: imageryUsed.join(';').substr(0, 255),
47030                 host: detected.host.substr(0, 255),
47031                 locale: detected.locale.substr(0, 255)
47032             };
47033
47034         if (comment) {
47035             tags.comment = comment.substr(0, 255);
47036         }
47037
47038         return tags;
47039     },
47040
47041
47042     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
47043         var that = this;
47044         oauth.xhr({
47045                 method: 'PUT',
47046                 path: '/api/0.6/changeset/create',
47047                 options: { header: { 'Content-Type': 'text/xml' } },
47048                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
47049             }, function(err, changeset_id) {
47050                 if (err) return callback(err);
47051                 oauth.xhr({
47052                     method: 'POST',
47053                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
47054                     options: { header: { 'Content-Type': 'text/xml' } },
47055                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
47056                 }, function(err) {
47057                     if (err) return callback(err);
47058                     // POST was successful, safe to call the callback.
47059                     // Still attempt to close changeset, but ignore response because #2667
47060                     // Add delay to allow for postgres replication #1646 #2678
47061                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
47062                     oauth.xhr({
47063                         method: 'PUT',
47064                         path: '/api/0.6/changeset/' + changeset_id + '/close',
47065                         options: { header: { 'Content-Type': 'text/xml' } }
47066                     }, function() { return true; });
47067                 });
47068             });
47069     },
47070
47071
47072     userDetails: function(callback) {
47073         if (userDetails) {
47074             callback(undefined, userDetails);
47075             return;
47076         }
47077
47078         function done(err, user_details) {
47079             if (err) return callback(err);
47080
47081             var u = user_details.getElementsByTagName('user')[0],
47082                 img = u.getElementsByTagName('img'),
47083                 image_url = '';
47084
47085             if (img && img[0] && img[0].getAttribute('href')) {
47086                 image_url = img[0].getAttribute('href');
47087             }
47088
47089             userDetails = {
47090                 display_name: u.attributes.display_name.value,
47091                 image_url: image_url,
47092                 id: u.attributes.id.value
47093             };
47094
47095             callback(undefined, userDetails);
47096         }
47097
47098         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
47099     },
47100
47101
47102     userChangesets: function(callback) {
47103         if (userChangesets) {
47104             callback(undefined, userChangesets);
47105             return;
47106         }
47107
47108         this.userDetails(function(err, user) {
47109             if (err) {
47110                 callback(err);
47111                 return;
47112             }
47113
47114             function done(err, changesets) {
47115                 if (err) {
47116                     callback(err);
47117                 } else {
47118                     userChangesets = Array.prototype.map.call(
47119                         changesets.getElementsByTagName('changeset'),
47120                         function (changeset) {
47121                             return { tags: getTags(changeset) };
47122                         }
47123                     );
47124                     callback(undefined, userChangesets);
47125                 }
47126             }
47127
47128             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
47129         });
47130     },
47131
47132
47133     status: function(callback) {
47134         function done(xml$$1) {
47135             // update blacklists
47136             var elements = xml$$1.getElementsByTagName('blacklist'),
47137                 regexes = [];
47138             for (var i = 0; i < elements.length; i++) {
47139                 var regex = elements[i].getAttribute('regex');  // needs unencode?
47140                 if (regex) {
47141                     regexes.push(regex);
47142                 }
47143             }
47144             if (regexes.length) {
47145                 blacklists = regexes;
47146             }
47147
47148
47149             if (rateLimitError) {
47150                 callback(rateLimitError, 'rateLimited');
47151             } else {
47152                 var apiStatus = xml$$1.getElementsByTagName('status'),
47153                     val = apiStatus[0].getAttribute('api');
47154
47155                 callback(undefined, val);
47156             }
47157         }
47158
47159         xml(urlroot + '/api/capabilities').get()
47160             .on('load', done)
47161             .on('error', callback);
47162     },
47163
47164
47165     imageryBlacklists: function() {
47166         return blacklists;
47167     },
47168
47169
47170     tileZoom: function(_) {
47171         if (!arguments.length) return tileZoom$1;
47172         tileZoom$1 = _;
47173         return this;
47174     },
47175
47176
47177     loadTiles: function(projection, dimensions, callback) {
47178         if (off) return;
47179
47180         var that = this,
47181             s = projection.scale() * 2 * Math.PI,
47182             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
47183             ts = 256 * Math.pow(2, z - tileZoom$1),
47184             origin = [
47185                 s / 2 - projection.translate()[0],
47186                 s / 2 - projection.translate()[1]
47187             ];
47188
47189         var tiles = d3geoTile()
47190             .scaleExtent([tileZoom$1, tileZoom$1])
47191             .scale(s)
47192             .size(dimensions)
47193             .translate(projection.translate())()
47194             .map(function(tile) {
47195                 var x = tile[0] * ts - origin[0],
47196                     y = tile[1] * ts - origin[1];
47197
47198                 return {
47199                     id: tile.toString(),
47200                     extent: geoExtent$$1(
47201                         projection.invert([x, y + ts]),
47202                         projection.invert([x + ts, y]))
47203                 };
47204             });
47205
47206         lodash.filter(inflight, function(v, i) {
47207             var wanted = lodash.find(tiles, function(tile) {
47208                 return i === tile.id;
47209             });
47210             if (!wanted) delete inflight[i];
47211             return !wanted;
47212         }).map(abortRequest$1);
47213
47214         tiles.forEach(function(tile) {
47215             var id = tile.id;
47216
47217             if (loadedTiles[id] || inflight[id]) return;
47218
47219             if (lodash.isEmpty(inflight)) {
47220                 dispatch$3.call('loading');
47221             }
47222
47223             inflight[id] = that.loadFromAPI(
47224                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
47225                 function(err, parsed) {
47226                     delete inflight[id];
47227                     if (!err) {
47228                         loadedTiles[id] = true;
47229                     }
47230
47231                     if (callback) {
47232                         callback(err, lodash.extend({ data: parsed }, tile));
47233                     }
47234
47235                     if (lodash.isEmpty(inflight)) {
47236                         dispatch$3.call('loaded');
47237                     }
47238                 }
47239             );
47240         });
47241     },
47242
47243
47244     switch: function(options) {
47245         urlroot = options.urlroot;
47246
47247         oauth.options(lodash.extend({
47248             url: urlroot,
47249             loading: authLoading,
47250             done: authDone
47251         }, options));
47252
47253         dispatch$3.call('change');
47254         this.reset();
47255         this.userChangesets(function() {});  // eagerly load user details/changesets
47256         return this;
47257     },
47258
47259
47260     toggle: function(_) {
47261         off = !_;
47262         return this;
47263     },
47264
47265
47266     loadedTiles: function(_) {
47267         if (!arguments.length) return loadedTiles;
47268         loadedTiles = _;
47269         return this;
47270     },
47271
47272
47273     logout: function() {
47274         userChangesets = undefined;
47275         userDetails = undefined;
47276         oauth.logout();
47277         dispatch$3.call('change');
47278         return this;
47279     },
47280
47281
47282     authenticate: function(callback) {
47283         var that = this;
47284         userChangesets = undefined;
47285         userDetails = undefined;
47286
47287         function done(err, res) {
47288             rateLimitError = undefined;
47289             dispatch$3.call('change');
47290             if (callback) callback(err, res);
47291             that.userChangesets(function() {});  // eagerly load user details/changesets
47292         }
47293
47294         return oauth.authenticate(done);
47295     }
47296 };
47297
47298 var endpoint = 'https://taginfo.openstreetmap.org/api/4/';
47299 var taginfoCache = {};
47300 var tag_sorts = {
47301         point: 'count_nodes',
47302         vertex: 'count_nodes',
47303         area: 'count_ways',
47304         line: 'count_ways'
47305     };
47306 var tag_sort_members = {
47307         point: 'count_node_members',
47308         vertex: 'count_node_members',
47309         area: 'count_way_members',
47310         line: 'count_way_members',
47311         relation: 'count_relation_members'
47312     };
47313 var tag_filters = {
47314         point: 'nodes',
47315         vertex: 'nodes',
47316         area: 'ways',
47317         line: 'ways'
47318     };
47319 var tag_members_fractions = {
47320         point: 'count_node_members_fraction',
47321         vertex: 'count_node_members_fraction',
47322         area: 'count_way_members_fraction',
47323         line: 'count_way_members_fraction',
47324         relation: 'count_relation_members_fraction'
47325     };
47326
47327
47328 function sets(parameters, n, o) {
47329     if (parameters.geometry && o[parameters.geometry]) {
47330         parameters[n] = o[parameters.geometry];
47331     }
47332     return parameters;
47333 }
47334
47335
47336 function setFilter(parameters) {
47337     return sets(parameters, 'filter', tag_filters);
47338 }
47339
47340
47341 function setSort(parameters) {
47342     return sets(parameters, 'sortname', tag_sorts);
47343 }
47344
47345
47346 function setSortMembers(parameters) {
47347     return sets(parameters, 'sortname', tag_sort_members);
47348 }
47349
47350
47351 function clean(parameters) {
47352     return lodash.omit(parameters, 'geometry', 'debounce');
47353 }
47354
47355
47356 function filterKeys(type) {
47357     var count_type = type ? 'count_' + type : 'count_all';
47358     return function(d) {
47359         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
47360     };
47361 }
47362
47363
47364 function filterMultikeys(prefix) {
47365     return function(d) {
47366         // d.key begins with prefix, and d.key contains no additional ':'s
47367         var re = new RegExp('^' + prefix + '(.*)$');
47368         var matches = d.key.match(re) || [];
47369         return (matches.length === 2 && matches[1].indexOf(':') === -1);
47370     };
47371 }
47372
47373
47374 function filterValues(allowUpperCase) {
47375     return function(d) {
47376         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
47377         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
47378         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
47379     };
47380 }
47381
47382
47383 function filterRoles(geometry) {
47384     return function(d) {
47385         if (d.role === '') return false; // exclude empty role
47386         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
47387         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
47388     };
47389 }
47390
47391
47392 function valKey(d) {
47393     return {
47394         value: d.key,
47395         title: d.key
47396     };
47397 }
47398
47399
47400 function valKeyDescription(d) {
47401     return {
47402         value: d.value,
47403         title: d.description || d.value
47404     };
47405 }
47406
47407
47408 function roleKey(d) {
47409     return {
47410         value: d.role,
47411         title: d.role
47412     };
47413 }
47414
47415
47416 // sort keys with ':' lower than keys without ':'
47417 function sortKeys(a, b) {
47418     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
47419         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
47420         : 0;
47421 }
47422
47423
47424 var debounced = lodash.debounce(json, 100, true);
47425
47426
47427 function request$1(url, debounce, callback) {
47428     if (taginfoCache[url]) {
47429         callback(null, taginfoCache[url]);
47430     } else if (debounce) {
47431         debounced(url, done);
47432     } else {
47433         json(url, done);
47434     }
47435
47436     function done(err, data) {
47437         if (!err) {
47438             taginfoCache[url] = data;
47439         }
47440         callback(err, data);
47441     }
47442 }
47443
47444
47445 var serviceTaginfo = {
47446
47447     init: function() { taginfoCache = {}; },
47448     reset: function() { taginfoCache = {}; },
47449
47450
47451     keys: function(parameters, callback) {
47452         var debounce = parameters.debounce;
47453         parameters = clean(setSort(parameters));
47454         request$1(endpoint + 'keys/all?' +
47455             utilQsString(lodash.extend({
47456                 rp: 10,
47457                 sortname: 'count_all',
47458                 sortorder: 'desc',
47459                 page: 1
47460             }, parameters)), debounce, function(err, d) {
47461                 if (err) {
47462                     callback(err);
47463                 } else {
47464                     var f = filterKeys(parameters.filter);
47465                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
47466                 }
47467             }
47468         );
47469     },
47470
47471
47472     multikeys: function(parameters, callback) {
47473         var debounce = parameters.debounce;
47474         parameters = clean(setSort(parameters));
47475         var prefix = parameters.query;
47476         request$1(endpoint + 'keys/all?' +
47477             utilQsString(lodash.extend({
47478                 rp: 25,
47479                 sortname: 'count_all',
47480                 sortorder: 'desc',
47481                 page: 1
47482             }, parameters)), debounce, function(err, d) {
47483                 if (err) {
47484                     callback(err);
47485                 } else {
47486                     var f = filterMultikeys(prefix);
47487                     callback(null, d.data.filter(f).map(valKey));
47488                 }
47489             }
47490         );
47491     },
47492
47493
47494     values: function(parameters, callback) {
47495         var debounce = parameters.debounce;
47496         parameters = clean(setSort(setFilter(parameters)));
47497         request$1(endpoint + 'key/values?' +
47498             utilQsString(lodash.extend({
47499                 rp: 25,
47500                 sortname: 'count_all',
47501                 sortorder: 'desc',
47502                 page: 1
47503             }, parameters)), debounce, function(err, d) {
47504                 if (err) {
47505                     callback(err);
47506                 } else {
47507                     // In most cases we prefer taginfo value results with lowercase letters.
47508                     // A few OSM keys expect values to contain uppercase values (see #3377).
47509                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
47510                     // but these are the fields where taginfo value lookup is most useful.
47511                     var re = /network|taxon|genus|species/;
47512                     var allowUpperCase = (parameters.key.match(re) !== null);
47513                     var f = filterValues(allowUpperCase);
47514                     callback(null, d.data.filter(f).map(valKeyDescription));
47515                 }
47516             }
47517         );
47518     },
47519
47520
47521     roles: function(parameters, callback) {
47522         var debounce = parameters.debounce;
47523         var geometry = parameters.geometry;
47524         parameters = clean(setSortMembers(parameters));
47525         request$1(endpoint + 'relation/roles?' +
47526             utilQsString(lodash.extend({
47527                 rp: 25,
47528                 sortname: 'count_all_members',
47529                 sortorder: 'desc',
47530                 page: 1
47531             }, parameters)), debounce, function(err, d) {
47532                 if (err) {
47533                     callback(err);
47534                 } else {
47535                     var f = filterRoles(geometry);
47536                     callback(null, d.data.filter(f).map(roleKey));
47537                 }
47538             }
47539         );
47540     },
47541
47542
47543     docs: function(parameters, callback) {
47544         var debounce = parameters.debounce;
47545         parameters = clean(setSort(parameters));
47546
47547         var path$$1 = 'key/wiki_pages?';
47548         if (parameters.value) path$$1 = 'tag/wiki_pages?';
47549         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
47550
47551         request$1(endpoint + path$$1 + utilQsString(parameters), debounce, function(err, d) {
47552             if (err) {
47553                 callback(err);
47554             } else {
47555                 callback(null, d.data);
47556             }
47557         });
47558     },
47559
47560
47561     endpoint: function(_) {
47562         if (!arguments.length) return endpoint;
47563         endpoint = _;
47564         return this;
47565     }
47566
47567 };
47568
47569 var jsonpCache = {};
47570 window.jsonpCache = jsonpCache;
47571
47572 function jsonpRequest(url, callback) {
47573
47574   if (window.JSONP_FIX) {
47575     if (window.JSONP_DELAY === 0) {
47576       callback(window.JSONP_FIX);
47577     } else {
47578       setTimeout(function() {
47579         callback(window.JSONP_FIX);
47580       }, window.JSONP_DELAY || 0);
47581     }
47582     return;
47583   }
47584
47585   function rand() {
47586     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47587       c = '', i = -1;
47588     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47589     return c;
47590   }
47591
47592   function create(url) {
47593     var e = url.match(/callback=(\w+)/),
47594       c = e ? e[1] : rand();
47595     jsonpCache[c] = function(data) {
47596       callback(data);
47597       delete jsonpCache[c];
47598       script.remove();
47599     };
47600     return 'jsonpCache.' + c;
47601   }
47602
47603   var cb = create(url),
47604     script = select('head')
47605     .append('script')
47606     .attr('type', 'text/javascript')
47607     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47608 }
47609
47610 var endpoint$1 = 'https://www.wikidata.org/w/api.php?';
47611
47612 var serviceWikidata = {
47613
47614     init: function() {},
47615     reset: function() {},
47616
47617
47618     // Given a Wikipedia language and article title, return an array of
47619     // corresponding Wikidata entities.
47620     itemsByTitle: function(lang, title, callback) {
47621         if (!title) {
47622             callback('', {});
47623             return;
47624         }
47625
47626         lang = lang || 'en';
47627         jsonpRequest(endpoint$1 + utilQsString({
47628             action: 'wbgetentities',
47629             format: 'json',
47630             sites: lang.replace(/-/g, '_') + 'wiki',
47631             titles: title,
47632             languages: 'en', // shrink response by filtering to one language
47633             callback: '{callback}'
47634         }), function(data) {
47635             if (!data || data.error) {
47636                 callback('', {});
47637             } else {
47638                 callback(title, data.entities || {});
47639             }
47640         });
47641     }
47642
47643 };
47644
47645 var endpoint$2 = 'https://en.wikipedia.org/w/api.php?';
47646
47647 var serviceWikipedia = {
47648
47649     init: function() {},
47650     reset: function() {},
47651
47652
47653     search: function(lang, query, callback) {
47654         if (!query) {
47655             callback('', []);
47656             return;
47657         }
47658
47659         lang = lang || 'en';
47660         jsonpRequest(endpoint$2.replace('en', lang) +
47661             utilQsString({
47662                 action: 'query',
47663                 list: 'search',
47664                 srlimit: '10',
47665                 srinfo: 'suggestion',
47666                 format: 'json',
47667                 callback: '{callback}',
47668                 srsearch: query
47669             }), function(data) {
47670                 if (!data || !data.query || !data.query.search || data.error) {
47671                     callback('', []);
47672                 } else {
47673                     var results = data.query.search.map(function(d) { return d.title; });
47674                     callback(query, results);
47675                 }
47676             }
47677         );
47678     },
47679
47680
47681     suggestions: function(lang, query, callback) {
47682         if (!query) {
47683             callback('', []);
47684             return;
47685         }
47686
47687         lang = lang || 'en';
47688         jsonpRequest(endpoint$2.replace('en', lang) +
47689             utilQsString({
47690                 action: 'opensearch',
47691                 namespace: 0,
47692                 suggest: '',
47693                 format: 'json',
47694                 callback: '{callback}',
47695                 search: query
47696             }), function(data) {
47697                 if (!data || data.error) {
47698                     callback('', []);
47699                 } else {
47700                     callback(data[0], data[1] || []);
47701                 }
47702             }
47703         );
47704     },
47705
47706
47707     translations: function(lang, title, callback) {
47708         if (!title) {
47709             callback({});
47710             return;
47711         }
47712
47713         jsonpRequest(endpoint$2.replace('en', lang) +
47714             utilQsString({
47715                 action: 'query',
47716                 prop: 'langlinks',
47717                 format: 'json',
47718                 callback: '{callback}',
47719                 lllimit: 500,
47720                 titles: title
47721             }), function(data) {
47722                 if (!data || !data.query || !data.query.pages || data.error) {
47723                     callback({});
47724                 } else {
47725                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47726                         translations = {};
47727                     if (list && list.langlinks) {
47728                         list.langlinks.forEach(function(d) {
47729                             translations[d.lang] = d['*'];
47730                         });
47731                     }
47732                     callback(translations);
47733                 }
47734             }
47735         );
47736     }
47737
47738 };
47739
47740 var services = {
47741     mapillary: serviceMapillary,
47742     geocoder: serviceNominatim,
47743     osm: serviceOsm,
47744     taginfo: serviceTaginfo,
47745     wikidata: serviceWikidata,
47746     wikipedia: serviceWikipedia
47747 };
47748
47749 function svgMapillaryImages(projection, context, dispatch$$1) {
47750     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47751         minZoom = 12,
47752         minViewfieldZoom = 17,
47753         layer = select(null),
47754         _mapillary;
47755
47756
47757     function init() {
47758         if (svgMapillaryImages.initialized) return;  // run once
47759         svgMapillaryImages.enabled = false;
47760         svgMapillaryImages.initialized = true;
47761     }
47762
47763
47764     function getMapillary() {
47765         if (services.mapillary && !_mapillary) {
47766             _mapillary = services.mapillary;
47767             _mapillary.event.on('loadedImages', throttledRedraw);
47768         } else if (!services.mapillary && _mapillary) {
47769             _mapillary = null;
47770         }
47771
47772         return _mapillary;
47773     }
47774
47775
47776     function showLayer() {
47777         var mapillary = getMapillary();
47778         if (!mapillary) return;
47779
47780         mapillary.loadViewer(context);
47781         editOn();
47782
47783         layer
47784             .style('opacity', 0)
47785             .transition()
47786             .duration(500)
47787             .style('opacity', 1)
47788             .on('end', function () { dispatch$$1.call('change'); });
47789     }
47790
47791
47792     function hideLayer() {
47793         var mapillary = getMapillary();
47794         if (mapillary) {
47795             mapillary.hideViewer();
47796         }
47797
47798         throttledRedraw.cancel();
47799
47800         layer
47801             .transition()
47802             .duration(500)
47803             .style('opacity', 0)
47804             .on('end', editOff);
47805     }
47806
47807
47808     function editOn() {
47809         layer.style('display', 'block');
47810     }
47811
47812
47813     function editOff() {
47814         layer.selectAll('.viewfield-group').remove();
47815         layer.style('display', 'none');
47816     }
47817
47818
47819     function click(d) {
47820         var mapillary = getMapillary();
47821         if (!mapillary) return;
47822
47823         context.map().centerEase(d.loc);
47824
47825         mapillary
47826             .selectedImage(d.key, true)
47827             .updateViewer(d.key, context)
47828             .showViewer();
47829     }
47830
47831
47832     function transform(d) {
47833         var t = svgPointTransform(projection)(d);
47834         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47835         return t;
47836     }
47837
47838
47839     function update() {
47840         var mapillary = getMapillary(),
47841             data = (mapillary ? mapillary.images(projection) : []),
47842             imageKey = mapillary ? mapillary.selectedImage() : null;
47843
47844         var markers = layer.selectAll('.viewfield-group')
47845             .data(data, function(d) { return d.key; });
47846
47847         markers.exit()
47848             .remove();
47849
47850         var enter = markers.enter()
47851             .append('g')
47852             .attr('class', 'viewfield-group')
47853             .classed('selected', function(d) { return d.key === imageKey; })
47854             .on('click', click);
47855
47856         markers = markers
47857             .merge(enter)
47858             .attr('transform', transform);
47859
47860
47861        var viewfields = markers.selectAll('.viewfield')
47862             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47863
47864         viewfields.exit()
47865             .remove();
47866
47867         viewfields.enter()
47868             .append('path')
47869             .attr('class', 'viewfield')
47870             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47871             .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');
47872
47873         markers.selectAll('circle')
47874             .data([0])
47875             .enter()
47876             .append('circle')
47877             .attr('dx', '0')
47878             .attr('dy', '0')
47879             .attr('r', '6');
47880     }
47881
47882
47883     function drawImages(selection$$1) {
47884         var enabled = svgMapillaryImages.enabled,
47885             mapillary = getMapillary();
47886
47887         layer = selection$$1.selectAll('.layer-mapillary-images')
47888             .data(mapillary ? [0] : []);
47889
47890         layer.exit()
47891             .remove();
47892
47893         layer = layer.enter()
47894             .append('g')
47895             .attr('class', 'layer-mapillary-images')
47896             .style('display', enabled ? 'block' : 'none')
47897             .merge(layer);
47898
47899         if (enabled) {
47900             if (mapillary && ~~context.map().zoom() >= minZoom) {
47901                 editOn();
47902                 update();
47903                 mapillary.loadImages(projection);
47904             } else {
47905                 editOff();
47906             }
47907         }
47908     }
47909
47910
47911     drawImages.enabled = function(_) {
47912         if (!arguments.length) return svgMapillaryImages.enabled;
47913         svgMapillaryImages.enabled = _;
47914         if (svgMapillaryImages.enabled) {
47915             showLayer();
47916         } else {
47917             hideLayer();
47918         }
47919         dispatch$$1.call('change');
47920         return this;
47921     };
47922
47923
47924     drawImages.supported = function() {
47925         return !!getMapillary();
47926     };
47927
47928
47929     init();
47930     return drawImages;
47931 }
47932
47933 function svgMapillarySigns(projection, context, dispatch$$1) {
47934     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47935         minZoom = 12,
47936         layer = select(null),
47937         _mapillary;
47938
47939
47940     function init() {
47941         if (svgMapillarySigns.initialized) return;  // run once
47942         svgMapillarySigns.enabled = false;
47943         svgMapillarySigns.initialized = true;
47944     }
47945
47946
47947     function getMapillary() {
47948         if (services.mapillary && !_mapillary) {
47949             _mapillary = services.mapillary;
47950             _mapillary.event.on('loadedSigns', throttledRedraw);
47951         } else if (!services.mapillary && _mapillary) {
47952             _mapillary = null;
47953         }
47954         return _mapillary;
47955     }
47956
47957
47958     function showLayer() {
47959         editOn();
47960     }
47961
47962
47963     function hideLayer() {
47964         throttledRedraw.cancel();
47965         editOff();
47966     }
47967
47968
47969     function editOn() {
47970         layer.style('display', 'block');
47971     }
47972
47973
47974     function editOff() {
47975         layer.selectAll('.icon-sign').remove();
47976         layer.style('display', 'none');
47977     }
47978
47979
47980     function click(d) {
47981         var mapillary = getMapillary();
47982         if (!mapillary) return;
47983
47984         context.map().centerEase(d.loc);
47985
47986         mapillary
47987             .selectedImage(d.key, true)
47988             .updateViewer(d.key, context)
47989             .showViewer();
47990     }
47991
47992
47993     function update() {
47994         var mapillary = getMapillary(),
47995             data = (mapillary ? mapillary.signs(projection) : []),
47996             imageKey = mapillary ? mapillary.selectedImage() : null;
47997
47998         var signs = layer.selectAll('.icon-sign')
47999             .data(data, function(d) { return d.key; });
48000
48001         signs.exit()
48002             .remove();
48003
48004         var enter = signs.enter()
48005             .append('foreignObject')
48006             .attr('class', 'icon-sign')
48007             .attr('width', '32px')      // for Firefox
48008             .attr('height', '32px')     // for Firefox
48009             .classed('selected', function(d) { return d.key === imageKey; })
48010             .on('click', click);
48011
48012         enter
48013             .append('xhtml:body')
48014             .attr('class', 'icon-sign-body')
48015             .html(mapillary.signHTML);
48016
48017         signs
48018             .merge(enter)
48019             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
48020             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
48021     }
48022
48023
48024     function drawSigns(selection$$1) {
48025         var enabled = svgMapillarySigns.enabled,
48026             mapillary = getMapillary();
48027
48028         layer = selection$$1.selectAll('.layer-mapillary-signs')
48029             .data(mapillary ? [0] : []);
48030
48031         layer.exit()
48032             .remove();
48033
48034         layer = layer.enter()
48035             .append('g')
48036             .attr('class', 'layer-mapillary-signs')
48037             .style('display', enabled ? 'block' : 'none')
48038             .merge(layer);
48039
48040         if (enabled) {
48041             if (mapillary && ~~context.map().zoom() >= minZoom) {
48042                 editOn();
48043                 update();
48044                 mapillary.loadSigns(context, projection);
48045             } else {
48046                 editOff();
48047             }
48048         }
48049     }
48050
48051
48052     drawSigns.enabled = function(_) {
48053         if (!arguments.length) return svgMapillarySigns.enabled;
48054         svgMapillarySigns.enabled = _;
48055         if (svgMapillarySigns.enabled) {
48056             showLayer();
48057         } else {
48058             hideLayer();
48059         }
48060         dispatch$$1.call('change');
48061         return this;
48062     };
48063
48064
48065     drawSigns.supported = function() {
48066         var mapillary = getMapillary();
48067         return (mapillary && mapillary.signsSupported());
48068     };
48069
48070
48071     init();
48072     return drawSigns;
48073 }
48074
48075 function svgOsm() {
48076     return function drawOsm(selection) {
48077         var layers = selection.selectAll('.layer-osm')
48078             .data(['areas', 'lines', 'hit', 'halo', 'label']);
48079
48080         layers.enter()
48081             .append('g')
48082             .attr('class', function(d) { return 'layer-osm layer-' + d; });
48083     };
48084 }
48085
48086 function svgLayers(projection, context) {
48087     var dispatch$$1 = dispatch('change'),
48088         svg = select(null),
48089         layers = [
48090             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
48091             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
48092             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
48093             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
48094             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
48095         ];
48096
48097
48098     function drawLayers(selection$$1) {
48099         svg = selection$$1.selectAll('.surface')
48100             .data([0]);
48101
48102         svg = svg.enter()
48103             .append('svg')
48104             .attr('class', 'surface')
48105             .merge(svg);
48106
48107         var defs = svg.selectAll('.surface-defs')
48108             .data([0]);
48109
48110         defs.enter()
48111             .append('defs')
48112             .attr('class', 'surface-defs');
48113
48114         var groups = svg.selectAll('.data-layer')
48115             .data(layers);
48116
48117         groups.exit()
48118             .remove();
48119
48120         groups.enter()
48121             .append('g')
48122             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
48123             .merge(groups)
48124             .each(function(d) { select(this).call(d.layer); });
48125     }
48126
48127
48128     drawLayers.all = function() {
48129         return layers;
48130     };
48131
48132
48133     drawLayers.layer = function(id) {
48134         var obj = lodash.find(layers, function(o) {return o.id === id;});
48135         return obj && obj.layer;
48136     };
48137
48138
48139     drawLayers.only = function(what) {
48140         var arr = [].concat(what);
48141         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
48142         return this;
48143     };
48144
48145
48146     drawLayers.remove = function(what) {
48147         var arr = [].concat(what);
48148         arr.forEach(function(id) {
48149             layers = lodash.reject(layers, function(o) {return o.id === id;});
48150         });
48151         dispatch$$1.call('change');
48152         return this;
48153     };
48154
48155
48156     drawLayers.add = function(what) {
48157         var arr = [].concat(what);
48158         arr.forEach(function(obj) {
48159             if ('id' in obj && 'layer' in obj) {
48160                 layers.push(obj);
48161             }
48162         });
48163         dispatch$$1.call('change');
48164         return this;
48165     };
48166
48167
48168     drawLayers.dimensions = function(_) {
48169         if (!arguments.length) return utilGetDimensions(svg);
48170         utilSetDimensions(svg, _);
48171         return this;
48172     };
48173
48174
48175     return utilRebind(drawLayers, dispatch$$1, 'on');
48176 }
48177
48178 function svgLines$$1(projection) {
48179     var detected = utilDetect();
48180
48181     var highway_stack = {
48182         motorway: 0,
48183         motorway_link: 1,
48184         trunk: 2,
48185         trunk_link: 3,
48186         primary: 4,
48187         primary_link: 5,
48188         secondary: 6,
48189         tertiary: 7,
48190         unclassified: 8,
48191         residential: 9,
48192         service: 10,
48193         footway: 11
48194     };
48195
48196     function waystack(a, b) {
48197         var as = 0, bs = 0;
48198         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
48199         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
48200         return as - bs;
48201     }
48202
48203
48204     return function drawLines(selection$$1, graph, entities, filter) {
48205         var ways = [], pathdata = {}, onewaydata = {},
48206             getPath = svgPath(projection, graph);
48207
48208         for (var i = 0; i < entities.length; i++) {
48209             var entity = entities[i],
48210                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
48211             if (outer) {
48212                 ways.push(entity.mergeTags(outer.tags));
48213             } else if (entity.geometry(graph) === 'line') {
48214                 ways.push(entity);
48215             }
48216         }
48217
48218         ways = ways.filter(getPath);
48219
48220         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
48221
48222         lodash.forOwn(pathdata, function(v, k) {
48223             onewaydata[k] = lodash(v)
48224                 .filter(function(d) { return d.isOneWay(); })
48225                 .map(svgOneWaySegments(projection, graph, 35))
48226                 .flatten()
48227                 .valueOf();
48228         });
48229
48230         var layer = selection$$1.selectAll('.layer-lines');
48231
48232         var layergroup = layer
48233             .selectAll('g.layergroup')
48234             .data(sequence(-10, 11));
48235
48236         layergroup = layergroup.enter()
48237             .append('g')
48238             .attr('class', function(d) { return 'layergroup layer' + String(d); })
48239             .merge(layergroup);
48240
48241
48242         var linegroup = layergroup
48243             .selectAll('g.linegroup')
48244             .data(['shadow', 'casing', 'stroke']);
48245
48246         linegroup = linegroup.enter()
48247             .append('g')
48248             .attr('class', function(d) { return 'linegroup line-' + d; })
48249             .merge(linegroup);
48250
48251
48252         var lines = linegroup
48253             .selectAll('path')
48254             .filter(filter)
48255             .data(
48256                 function() { return pathdata[this.parentNode.__data__] || []; },
48257                 osmEntity$$1.key
48258             );
48259
48260         lines.exit()
48261             .remove();
48262
48263         // Optimization: call simple TagClasses only on enter selection. This
48264         // works because osmEntity.key is defined to include the entity v attribute.
48265         lines.enter()
48266             .append('path')
48267             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
48268             .call(svgTagClasses())
48269             .merge(lines)
48270                 .sort(waystack)
48271                 .attr('d', getPath)
48272                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
48273
48274
48275         var onewaygroup = layergroup
48276             .selectAll('g.onewaygroup')
48277             .data(['oneway']);
48278
48279         onewaygroup = onewaygroup.enter()
48280             .append('g')
48281             .attr('class', 'onewaygroup')
48282             .merge(onewaygroup);
48283
48284
48285         var oneways = onewaygroup
48286             .selectAll('path')
48287             .filter(filter)
48288             .data(
48289                 function() { return onewaydata[this.parentNode.__data__] || []; },
48290                 function(d) { return [d.id, d.index]; }
48291             );
48292
48293         oneways.exit()
48294             .remove();
48295
48296         oneways = oneways.enter()
48297             .append('path')
48298             .attr('class', 'oneway')
48299             .attr('marker-mid', 'url(#oneway-marker)')
48300             .merge(oneways)
48301             .attr('d', function(d) { return d.d; });
48302
48303         if (detected.ie) {
48304             oneways.each(function() { this.parentNode.insertBefore(this, this); });
48305         }
48306     };
48307 }
48308
48309 function svgMidpoints$$1(projection, context) {
48310
48311     return function drawMidpoints(selection, graph, entities, filter, extent) {
48312         var poly = extent.polygon(),
48313             midpoints = {};
48314
48315         for (var i = 0; i < entities.length; i++) {
48316             var entity = entities[i];
48317
48318             if (entity.type !== 'way')
48319                 continue;
48320             if (!filter(entity))
48321                 continue;
48322             if (context.selectedIDs().indexOf(entity.id) < 0)
48323                 continue;
48324
48325             var nodes = graph.childNodes(entity);
48326             for (var j = 0; j < nodes.length - 1; j++) {
48327
48328                 var a = nodes[j],
48329                     b = nodes[j + 1],
48330                     id = [a.id, b.id].sort().join('-');
48331
48332                 if (midpoints[id]) {
48333                     midpoints[id].parents.push(entity);
48334                 } else {
48335                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
48336                         var point = geoInterp(a.loc, b.loc, 0.5),
48337                             loc = null;
48338
48339                         if (extent.intersects(point)) {
48340                             loc = point;
48341                         } else {
48342                             for (var k = 0; k < 4; k++) {
48343                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
48344                                 if (point &&
48345                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
48346                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
48347                                 {
48348                                     loc = point;
48349                                     break;
48350                                 }
48351                             }
48352                         }
48353
48354                         if (loc) {
48355                             midpoints[id] = {
48356                                 type: 'midpoint',
48357                                 id: id,
48358                                 loc: loc,
48359                                 edge: [a.id, b.id],
48360                                 parents: [entity]
48361                             };
48362                         }
48363                     }
48364                 }
48365             }
48366         }
48367
48368
48369         function midpointFilter(d) {
48370             if (midpoints[d.id])
48371                 return true;
48372
48373             for (var i = 0; i < d.parents.length; i++) {
48374                 if (filter(d.parents[i])) {
48375                     return true;
48376                 }
48377             }
48378
48379             return false;
48380         }
48381
48382
48383         var layer = selection.selectAll('.layer-hit');
48384
48385         var groups = layer
48386             .selectAll('g.midpoint')
48387             .filter(midpointFilter)
48388             .data(lodash.values(midpoints), function(d) { return d.id; });
48389
48390         groups.exit()
48391             .remove();
48392
48393         var enter = groups.enter()
48394             .insert('g', ':first-child')
48395             .attr('class', 'midpoint');
48396
48397         enter.append('polygon')
48398             .attr('points', '-6,8 10,0 -6,-8')
48399             .attr('class', 'shadow');
48400
48401         enter.append('polygon')
48402             .attr('points', '-3,4 5,0 -3,-4')
48403             .attr('class', 'fill');
48404
48405         groups = groups
48406             .merge(enter)
48407             .attr('transform', function(d) {
48408                 var translate = svgPointTransform(projection),
48409                     a = graph.entity(d.edge[0]),
48410                     b = graph.entity(d.edge[1]),
48411                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
48412                 return translate(d) + ' rotate(' + angleVal + ')';
48413             })
48414             .call(svgTagClasses().tags(
48415                 function(d) { return d.parents[0].tags; }
48416             ));
48417
48418         // Propagate data bindings.
48419         groups.select('polygon.shadow');
48420         groups.select('polygon.fill');
48421
48422     };
48423 }
48424
48425 function svgOneWaySegments(projection, graph, dt) {
48426     return function(entity) {
48427         var a,
48428             b,
48429             i = 0,
48430             offset = dt,
48431             segments = [],
48432             clip = identity$5().clipExtent(projection.clipExtent()).stream,
48433             coordinates = graph.childNodes(entity).map(function(n) {
48434                 return n.loc;
48435             });
48436
48437         if (entity.tags.oneway === '-1') coordinates.reverse();
48438
48439         geoStream({
48440             type: 'LineString',
48441             coordinates: coordinates
48442         }, projection.stream(clip({
48443             lineStart: function() {},
48444             lineEnd: function() {
48445                 a = null;
48446             },
48447             point: function(x, y) {
48448                 b = [x, y];
48449
48450                 if (a) {
48451                     var span = geoEuclideanDistance(a, b) - offset;
48452
48453                     if (span >= 0) {
48454                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
48455                             dx = dt * Math.cos(angle),
48456                             dy = dt * Math.sin(angle),
48457                             p = [a[0] + offset * Math.cos(angle),
48458                                  a[1] + offset * Math.sin(angle)];
48459
48460                         var segment = 'M' + a[0] + ',' + a[1] +
48461                                       'L' + p[0] + ',' + p[1];
48462
48463                         for (span -= dt; span >= 0; span -= dt) {
48464                             p[0] += dx;
48465                             p[1] += dy;
48466                             segment += 'L' + p[0] + ',' + p[1];
48467                         }
48468
48469                         segment += 'L' + b[0] + ',' + b[1];
48470                         segments.push({id: entity.id, index: i, d: segment});
48471                     }
48472
48473                     offset = -span;
48474                     i++;
48475                 }
48476
48477                 a = b;
48478             }
48479         })));
48480
48481         return segments;
48482     };
48483 }
48484
48485 function svgPath(projection, graph, isArea) {
48486
48487     // Explanation of magic numbers:
48488     // "padding" here allows space for strokes to extend beyond the viewport,
48489     // so that the stroke isn't drawn along the edge of the viewport when
48490     // the shape is clipped.
48491     //
48492     // When drawing lines, pad viewport by 5px.
48493     // When drawing areas, pad viewport by 65px in each direction to allow
48494     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
48495
48496     var cache = {},
48497         padding = isArea ? 65 : 5,
48498         viewport = projection.clipExtent(),
48499         paddedExtent = [
48500             [viewport[0][0] - padding, viewport[0][1] - padding],
48501             [viewport[1][0] + padding, viewport[1][1] + padding]
48502         ],
48503         clip = identity$5().clipExtent(paddedExtent).stream,
48504         project = projection.stream,
48505         path$$1 = index$4()
48506             .projection({stream: function(output) { return project(clip(output)); }});
48507
48508     return function(entity) {
48509         if (entity.id in cache) {
48510             return cache[entity.id];
48511         } else {
48512             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
48513         }
48514     };
48515 }
48516
48517 function svgPoints$$1(projection, context) {
48518
48519     function markerPath(selection, klass) {
48520         selection
48521             .attr('class', klass)
48522             .attr('transform', 'translate(-8, -23)')
48523             .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');
48524     }
48525
48526     function sortY(a, b) {
48527         return b.loc[1] - a.loc[1];
48528     }
48529
48530
48531     return function drawPoints(selection, graph, entities, filter) {
48532         var wireframe = context.surface().classed('fill-wireframe'),
48533             points = wireframe ? [] : lodash.filter(entities, function(e) {
48534                 return e.geometry(graph) === 'point';
48535             });
48536
48537         points.sort(sortY);
48538
48539         var layer = selection.selectAll('.layer-hit');
48540
48541         var groups = layer.selectAll('g.point')
48542             .filter(filter)
48543             .data(points, osmEntity$$1.key);
48544
48545         groups.exit()
48546             .remove();
48547
48548         var enter = groups.enter()
48549             .append('g')
48550             .attr('class', function(d) { return 'node point ' + d.id; })
48551             .order();
48552
48553         enter.append('path')
48554             .call(markerPath, 'shadow');
48555
48556         enter.append('path')
48557             .call(markerPath, 'stroke');
48558
48559         enter.append('use')
48560             .attr('transform', 'translate(-5, -19)')
48561             .attr('class', 'icon')
48562             .attr('width', '11px')
48563             .attr('height', '11px');
48564
48565         groups = groups
48566             .merge(enter)
48567             .attr('transform', svgPointTransform(projection))
48568             .call(svgTagClasses());
48569
48570         // Selecting the following implicitly
48571         // sets the data (point entity) on the element
48572         groups.select('.shadow');
48573         groups.select('.stroke');
48574         groups.select('.icon')
48575             .attr('xlink:href', function(entity) {
48576                 var preset = context.presets().match(entity, graph);
48577                 return (preset && preset.icon) ? '#' + preset.icon + '-11' : '';
48578             });
48579     };
48580 }
48581
48582 function svgRelationMemberTags(graph) {
48583     return function(entity) {
48584         var tags = entity.tags;
48585         graph.parentRelations(entity).forEach(function(relation) {
48586             var type = relation.tags.type;
48587             if (type === 'multipolygon' || type === 'boundary') {
48588                 tags = lodash.extend({}, relation.tags, tags);
48589             }
48590         });
48591         return tags;
48592     };
48593 }
48594
48595 function svgTagClasses() {
48596     var primaries = [
48597             'building', 'highway', 'railway', 'waterway', 'aeroway',
48598             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48599             'leisure', 'military', 'place'
48600         ],
48601         statuses = [
48602             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48603             'razed', 'demolished', 'obliterated'
48604         ],
48605         secondaries = [
48606             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48607             'surface', 'tracktype', 'crossing'
48608         ],
48609         tagClassRe = /^tag-/,
48610         tags = function(entity) { return entity.tags; };
48611
48612
48613     var tagClasses = function(selection$$1) {
48614         selection$$1.each(function tagClassesEach(entity) {
48615             var value = this.className,
48616                 classes, primary, status;
48617
48618             if (value.baseVal !== undefined) value = value.baseVal;
48619
48620             classes = value.trim().split(/\s+/).filter(function(name) {
48621                 return name.length && !tagClassRe.test(name);
48622             }).join(' ');
48623
48624             var t = tags(entity), i, k, v;
48625
48626             // pick at most one primary classification tag..
48627             for (i = 0; i < primaries.length; i++) {
48628                 k = primaries[i];
48629                 v = t[k];
48630                 if (!v || v === 'no') continue;
48631
48632                 primary = k;
48633                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48634                     status = v;
48635                     classes += ' tag-' + k;
48636                 } else {
48637                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48638                 }
48639
48640                 break;
48641             }
48642
48643             // add at most one status tag, only if relates to primary tag..
48644             if (!status) {
48645                 for (i = 0; i < statuses.length; i++) {
48646                     k = statuses[i];
48647                     v = t[k];
48648                     if (!v || v === 'no') continue;
48649
48650                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48651                         status = k;
48652                     }
48653                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48654                         status = k;
48655                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48656                         status = k;
48657                         primary = v;
48658                         classes += ' tag-' + v;
48659                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48660
48661                     if (status) break;
48662                 }
48663             }
48664
48665             if (status) {
48666                 classes += ' tag-status tag-status-' + status;
48667             }
48668
48669             // add any secondary (structure) tags
48670             for (i = 0; i < secondaries.length; i++) {
48671                 k = secondaries[i];
48672                 v = t[k];
48673                 if (!v || v === 'no') continue;
48674                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48675             }
48676
48677             // For highways, look for surface tagging..
48678             if (primary === 'highway') {
48679                 var paved = (t.highway !== 'track');
48680                 for (k in t) {
48681                     v = t[k];
48682                     if (k in osmPavedTags) {
48683                         paved = !!osmPavedTags[k][v];
48684                         break;
48685                     }
48686                 }
48687                 if (!paved) {
48688                     classes += ' tag-unpaved';
48689                 }
48690             }
48691
48692             classes = classes.trim();
48693
48694             if (classes !== value) {
48695                 select(this).attr('class', classes);
48696             }
48697         });
48698     };
48699
48700
48701     tagClasses.tags = function(_) {
48702         if (!arguments.length) return tags;
48703         tags = _;
48704         return tagClasses;
48705     };
48706
48707     return tagClasses;
48708 }
48709
48710 function svgTurns(projection) {
48711
48712     return function drawTurns(selection, graph, turns) {
48713
48714         function key(turn) {
48715             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48716         }
48717
48718         function icon(turn) {
48719             var u = turn.u ? '-u' : '';
48720             if (!turn.restriction)
48721                 return '#turn-yes' + u;
48722             var restriction = graph.entity(turn.restriction).tags.restriction;
48723             return '#turn-' +
48724                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48725         }
48726
48727         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48728             .data(turns, key);
48729
48730         groups.exit()
48731             .remove();
48732
48733
48734         var enter = groups.enter()
48735             .append('g')
48736             .attr('class', 'turn');
48737
48738         var nEnter = enter
48739             .filter(function (turn) { return !turn.u; });
48740
48741         nEnter.append('rect')
48742             .attr('transform', 'translate(-22, -12)')
48743             .attr('width', '44')
48744             .attr('height', '24');
48745
48746         nEnter.append('use')
48747             .attr('transform', 'translate(-22, -12)')
48748             .attr('width', '44')
48749             .attr('height', '24');
48750
48751
48752         var uEnter = enter
48753             .filter(function (turn) { return turn.u; });
48754
48755         uEnter.append('circle')
48756             .attr('r', '16');
48757
48758         uEnter.append('use')
48759             .attr('transform', 'translate(-16, -16)')
48760             .attr('width', '32')
48761             .attr('height', '32');
48762
48763
48764         groups = groups
48765             .merge(enter);
48766
48767         groups
48768             .attr('transform', function (turn) {
48769                 var v = graph.entity(turn.via.node),
48770                     t = graph.entity(turn.to.node),
48771                     a = geoAngle(v, t, projection),
48772                     p = projection(v.loc),
48773                     r = turn.u ? 0 : 60;
48774
48775                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48776                     'rotate(' + a * 180 / Math.PI + ')';
48777             });
48778
48779         groups.select('use')
48780             .attr('xlink:href', icon);
48781
48782         groups.select('rect');
48783         groups.select('circle');
48784
48785         return this;
48786     };
48787 }
48788
48789 function svgVertices$$1(projection, context) {
48790     var radiuses = {
48791         //       z16-, z17, z18+, tagged
48792         shadow: [6,    7.5,   7.5,  11.5],
48793         stroke: [2.5,  3.5,   3.5,  7],
48794         fill:   [1,    1.5,   1.5,  1.5]
48795     };
48796
48797     var hover;
48798
48799
48800     function siblingAndChildVertices(ids, graph, extent$$1) {
48801         var vertices = {};
48802
48803         function addChildVertices(entity) {
48804             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48805                 var i;
48806                 if (entity.type === 'way') {
48807                     for (i = 0; i < entity.nodes.length; i++) {
48808                         addChildVertices(graph.entity(entity.nodes[i]));
48809                     }
48810                 } else if (entity.type === 'relation') {
48811                     for (i = 0; i < entity.members.length; i++) {
48812                         var member = context.hasEntity(entity.members[i].id);
48813                         if (member) {
48814                             addChildVertices(member);
48815                         }
48816                     }
48817                 } else if (entity.intersects(extent$$1, graph)) {
48818                     vertices[entity.id] = entity;
48819                 }
48820             }
48821         }
48822
48823         ids.forEach(function(id) {
48824             var entity = context.hasEntity(id);
48825             if (entity && entity.type === 'node') {
48826                 vertices[entity.id] = entity;
48827                 context.graph().parentWays(entity).forEach(function(entity) {
48828                     addChildVertices(entity);
48829                 });
48830             } else if (entity) {
48831                 addChildVertices(entity);
48832             }
48833         });
48834
48835         return vertices;
48836     }
48837
48838
48839     function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings) {
48840
48841         function icon(entity) {
48842             if (entity.id in icons) return icons[entity.id];
48843             icons[entity.id] =
48844                 entity.hasInterestingTags() &&
48845                 context.presets().match(entity, graph).icon;
48846             return icons[entity.id];
48847         }
48848
48849         function setClass(klass) {
48850             return function(entity) {
48851                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48852             };
48853         }
48854
48855         function setAttributes(selection$$1) {
48856             ['shadow','stroke','fill'].forEach(function(klass) {
48857                 var rads = radiuses[klass];
48858                 selection$$1.selectAll('.' + klass)
48859                     .each(function(entity) {
48860                         var i = z && icon(entity),
48861                             c = i ? 0.5 : 0,
48862                             r = rads[i ? 3 : z];
48863
48864                         // slightly increase the size of unconnected endpoints #3775
48865                         if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
48866                             r += 1.5;
48867                         }
48868
48869                         this.setAttribute('cx', c);
48870                         this.setAttribute('cy', -c);
48871                         this.setAttribute('r', r);
48872                         if (i && klass === 'fill') {
48873                             this.setAttribute('visibility', 'hidden');
48874                         } else {
48875                             this.removeAttribute('visibility');
48876                         }
48877                     });
48878             });
48879
48880             selection$$1.selectAll('use')
48881                 .each(function() {
48882                     if (z) {
48883                         this.removeAttribute('visibility');
48884                     } else {
48885                         this.setAttribute('visibility', 'hidden');
48886                     }
48887                 });
48888         }
48889
48890
48891         siblings = siblings || {};
48892
48893         var icons = {},
48894             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48895
48896         var groups = selection$$1
48897             .data(vertices, osmEntity$$1.key);
48898
48899         groups.exit()
48900             .remove();
48901
48902         var enter = groups.enter()
48903             .append('g')
48904             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48905
48906         enter.append('circle')
48907             .each(setClass('shadow'));
48908
48909         enter.append('circle')
48910             .each(setClass('stroke'));
48911
48912         // Vertices with icons get a `use`.
48913         enter.filter(function(d) { return icon(d); })
48914             .append('use')
48915             .attr('transform', 'translate(-5, -6)')
48916             .attr('xlink:href', function(d) { return '#' + icon(d) + '-11'; })
48917             .attr('width', '11px')
48918             .attr('height', '11px')
48919             .each(setClass('icon'));
48920
48921         // Vertices with tags get a fill.
48922         enter.filter(function(d) { return d.hasInterestingTags(); })
48923             .append('circle')
48924             .each(setClass('fill'));
48925
48926         groups
48927             .merge(enter)
48928             .attr('transform', svgPointTransform(projection))
48929             .classed('sibling', function(entity) { return entity.id in siblings; })
48930             .classed('shared', function(entity) { return graph.isShared(entity); })
48931             .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
48932             .call(setAttributes);
48933     }
48934
48935
48936     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48937         var siblings = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48938             wireframe = context.surface().classed('fill-wireframe'),
48939             vertices = [];
48940
48941         for (var i = 0; i < entities.length; i++) {
48942             var entity = entities[i],
48943                 geometry = entity.geometry(graph);
48944
48945             if (wireframe && geometry === 'point') {
48946                 vertices.push(entity);
48947                 continue;
48948             }
48949
48950             if (geometry !== 'vertex')
48951                 continue;
48952
48953             if (entity.id in siblings ||
48954                 entity.hasInterestingTags() ||
48955                 entity.isEndpoint(graph) ||
48956                 entity.isConnected(graph)) {
48957                 vertices.push(entity);
48958             }
48959         }
48960
48961         var layer = selection$$1.selectAll('.layer-hit');
48962         layer.selectAll('g.vertex.vertex-persistent')
48963             .filter(filter)
48964             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings);
48965
48966         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48967     }
48968
48969
48970     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48971         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48972         var layer = selection$$1.selectAll('.layer-hit');
48973
48974         layer.selectAll('g.vertex.vertex-hover')
48975             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48976     }
48977
48978
48979     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48980         if (target === hover) return;
48981         hover = target;
48982         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48983     };
48984
48985     return drawVertices;
48986 }
48987
48988 function behaviorEdit(context) {
48989
48990     function edit() {
48991         context.map()
48992             .minzoom(context.minEditableZoom());
48993     }
48994
48995
48996     edit.off = function() {
48997         context.map()
48998             .minzoom(0);
48999     };
49000
49001
49002     return edit;
49003 }
49004
49005 /*
49006    The hover behavior adds the `.hover` class on mouseover to all elements to which
49007    the identical datum is bound, and removes it on mouseout.
49008
49009    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
49010    representation may consist of several elements scattered throughout the DOM hierarchy.
49011    Only one of these elements can have the :hover pseudo-class, but all of them will
49012    have the .hover class.
49013  */
49014 function behaviorHover() {
49015     var dispatch$$1 = dispatch('hover'),
49016         selection$$1 = select(null),
49017         buttonDown,
49018         altDisables,
49019         target;
49020
49021
49022     function keydown() {
49023         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49024             dispatch$$1.call('hover', this, null);
49025             selection$$1.selectAll('.hover')
49026                 .classed('hover-suppressed', true)
49027                 .classed('hover', false);
49028         }
49029     }
49030
49031
49032     function keyup() {
49033         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49034             dispatch$$1.call('hover', this, target ? target.id : null);
49035             selection$$1.selectAll('.hover-suppressed')
49036                 .classed('hover-suppressed', false)
49037                 .classed('hover', true);
49038         }
49039     }
49040
49041
49042     var hover = function(__) {
49043         selection$$1 = __;
49044
49045         selection$$1
49046             .on('mouseover.hover', mouseover)
49047             .on('mouseout.hover', mouseout)
49048             .on('mousedown.hover', mousedown);
49049
49050         select(window)
49051             .on('keydown.hover', keydown)
49052             .on('keyup.hover', keyup);
49053
49054
49055         function mouseover() {
49056             if (buttonDown) return;
49057             var target = event.target;
49058             enter(target ? target.__data__ : null);
49059         }
49060
49061
49062         function mouseout() {
49063             if (buttonDown) return;
49064             var target = event.relatedTarget;
49065             enter(target ? target.__data__ : null);
49066         }
49067
49068
49069         function mousedown() {
49070             buttonDown = true;
49071             select(window)
49072                 .on('mouseup.hover', mouseup, true);
49073         }
49074
49075
49076         function mouseup() {
49077             buttonDown = false;
49078             select(window)
49079                 .on('mouseup.hover', null, true);
49080         }
49081
49082
49083         function enter(d) {
49084             if (d === target) return;
49085             target = d;
49086
49087             selection$$1.selectAll('.hover')
49088                 .classed('hover', false);
49089             selection$$1.selectAll('.hover-suppressed')
49090                 .classed('hover-suppressed', false);
49091
49092             if (target instanceof osmEntity$$1) {
49093                 var selector$$1 = '.' + target.id;
49094
49095                 if (target.type === 'relation') {
49096                     target.members.forEach(function(member) {
49097                         selector$$1 += ', .' + member.id;
49098                     });
49099                 }
49100
49101                 var suppressed = altDisables && event && event.altKey;
49102
49103                 selection$$1.selectAll(selector$$1)
49104                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
49105
49106                 dispatch$$1.call('hover', this, target.id);
49107             } else {
49108                 dispatch$$1.call('hover', this, null);
49109             }
49110         }
49111
49112     };
49113
49114
49115     hover.off = function(selection$$1) {
49116         selection$$1.selectAll('.hover')
49117             .classed('hover', false);
49118         selection$$1.selectAll('.hover-suppressed')
49119             .classed('hover-suppressed', false);
49120
49121         selection$$1
49122             .on('mouseover.hover', null)
49123             .on('mouseout.hover', null)
49124             .on('mousedown.hover', null);
49125
49126         select(window)
49127             .on('keydown.hover', null)
49128             .on('keyup.hover', null);
49129     };
49130
49131
49132     hover.altDisables = function(_) {
49133         if (!arguments.length) return altDisables;
49134         altDisables = _;
49135         return hover;
49136     };
49137
49138
49139     return utilRebind(hover, dispatch$$1, 'on');
49140 }
49141
49142 function behaviorTail() {
49143     var text$$1,
49144         container,
49145         xmargin = 25,
49146         tooltipSize = [0, 0],
49147         selectionSize = [0, 0];
49148
49149
49150     function tail(selection$$1) {
49151         if (!text$$1) return;
49152
49153         select(window)
49154             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
49155
49156         container = select(document.body)
49157             .append('div')
49158             .style('display', 'none')
49159             .attr('class', 'tail tooltip-inner');
49160
49161         container.append('div')
49162             .text(text$$1);
49163
49164         selection$$1
49165             .on('mousemove.tail', mousemove)
49166             .on('mouseenter.tail', mouseenter)
49167             .on('mouseleave.tail', mouseleave);
49168
49169         container
49170             .on('mousemove.tail', mousemove);
49171
49172         tooltipSize = utilGetDimensions(container);
49173         selectionSize = utilGetDimensions(selection$$1);
49174
49175
49176         function show() {
49177             container.style('display', 'block');
49178             tooltipSize = utilGetDimensions(container);
49179         }
49180
49181
49182         function mousemove() {
49183             if (container.style('display') === 'none') show();
49184             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
49185                 -tooltipSize[0] - xmargin : xmargin;
49186             container.classed('left', xoffset > 0);
49187             utilSetTransform(container, event.clientX + xoffset, event.clientY);
49188         }
49189
49190
49191         function mouseleave() {
49192             if (event.relatedTarget !== container.node()) {
49193                 container.style('display', 'none');
49194             }
49195         }
49196
49197
49198         function mouseenter() {
49199             if (event.relatedTarget !== container.node()) {
49200                 show();
49201             }
49202         }
49203     }
49204
49205
49206     tail.off = function(selection$$1) {
49207         if (!text$$1) return;
49208
49209         container
49210             .on('mousemove.tail', null)
49211             .remove();
49212
49213         selection$$1
49214             .on('mousemove.tail', null)
49215             .on('mouseenter.tail', null)
49216             .on('mouseleave.tail', null);
49217
49218         select(window)
49219             .on('resize.tail', null);
49220     };
49221
49222
49223     tail.text = function(_) {
49224         if (!arguments.length) return text$$1;
49225         text$$1 = _;
49226         return tail;
49227     };
49228
49229
49230     return tail;
49231 }
49232
49233 behaviorDraw.usedTails = {};
49234 behaviorDraw.disableSpace = false;
49235 behaviorDraw.lastSpace = null;
49236
49237
49238 function behaviorDraw(context) {
49239     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
49240             'clickNode', 'undo', 'cancel', 'finish'),
49241         keybinding = d3keybinding('draw'),
49242         hover = behaviorHover(context)
49243             .altDisables(true)
49244             .on('hover', context.ui().sidebar.hover),
49245         tail = behaviorTail(),
49246         edit = behaviorEdit(context),
49247         closeTolerance = 4,
49248         tolerance = 12,
49249         mouseLeave = false,
49250         lastMouse = null,
49251         cached = behaviorDraw;
49252
49253
49254     function datum() {
49255         if (event.altKey) return {};
49256
49257         if (event.type === 'keydown') {
49258             return (lastMouse && lastMouse.target.__data__) || {};
49259         } else {
49260             return event.target.__data__ || {};
49261         }
49262     }
49263
49264
49265     function mousedown() {
49266
49267         function point() {
49268             var p = context.container().node();
49269             return touchId !== null ? touches(p).filter(function(p) {
49270                 return p.identifier === touchId;
49271             })[0] : mouse(p);
49272         }
49273
49274         var element = select(this),
49275             touchId = event.touches ? event.changedTouches[0].identifier : null,
49276             t1 = +new Date(),
49277             p1 = point();
49278
49279         element.on('mousemove.draw', null);
49280
49281         select(window).on('mouseup.draw', function() {
49282             var t2 = +new Date(),
49283                 p2 = point(),
49284                 dist = geoEuclideanDistance(p1, p2);
49285
49286             element.on('mousemove.draw', mousemove);
49287             select(window).on('mouseup.draw', null);
49288
49289             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
49290                 // Prevent a quick second click
49291                 select(window).on('click.draw-block', function() {
49292                     event.stopPropagation();
49293                 }, true);
49294
49295                 context.map().dblclickEnable(false);
49296
49297                 window.setTimeout(function() {
49298                     context.map().dblclickEnable(true);
49299                     select(window).on('click.draw-block', null);
49300                 }, 500);
49301
49302                 click();
49303             }
49304         }, true);
49305     }
49306
49307
49308     function mousemove() {
49309         lastMouse = event;
49310         dispatch$$1.call('move', this, datum());
49311     }
49312
49313
49314     function mouseenter() {
49315         mouseLeave = false;
49316     }
49317
49318
49319     function mouseleave() {
49320         mouseLeave = true;
49321     }
49322
49323
49324     function click() {
49325         var d = datum();
49326         if (d.type === 'way') {
49327             var dims = context.map().dimensions(),
49328                 mouse$$1 = context.mouse(),
49329                 pad = 5,
49330                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
49331                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
49332
49333             if (trySnap) {
49334                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
49335                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
49336                 dispatch$$1.call('clickWay', this, choice.loc, edge);
49337             } else {
49338                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49339             }
49340
49341         } else if (d.type === 'node') {
49342             dispatch$$1.call('clickNode', this, d);
49343
49344         } else {
49345             dispatch$$1.call('click', this, context.map().mouseCoordinates());
49346         }
49347     }
49348
49349
49350     function space() {
49351         var currSpace = context.mouse();
49352         if (cached.disableSpace && cached.lastSpace) {
49353             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
49354             if (dist > tolerance) {
49355                 cached.disableSpace = false;
49356             }
49357         }
49358
49359         if (cached.disableSpace || mouseLeave || !lastMouse) return;
49360
49361         // user must move mouse or release space bar to allow another click
49362         cached.lastSpace = currSpace;
49363         cached.disableSpace = true;
49364
49365         select(window).on('keyup.space-block', function() {
49366             cached.disableSpace = false;
49367             select(window).on('keyup.space-block', null);
49368         });
49369
49370         event.preventDefault();
49371         click();
49372     }
49373
49374
49375     function backspace() {
49376         event.preventDefault();
49377         dispatch$$1.call('undo');
49378     }
49379
49380
49381     function del() {
49382         event.preventDefault();
49383         dispatch$$1.call('cancel');
49384     }
49385
49386
49387     function ret() {
49388         event.preventDefault();
49389         dispatch$$1.call('finish');
49390     }
49391
49392
49393     function draw(selection$$1) {
49394         context.install(hover);
49395         context.install(edit);
49396
49397         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49398             context.install(tail);
49399         }
49400
49401         keybinding
49402             .on('⌫', backspace)
49403             .on('⌦', del)
49404             .on('⎋', ret)
49405             .on('↩', ret)
49406             .on('space', space)
49407             .on('⌥space', space);
49408
49409         selection$$1
49410             .on('mouseenter.draw', mouseenter)
49411             .on('mouseleave.draw', mouseleave)
49412             .on('mousedown.draw', mousedown)
49413             .on('mousemove.draw', mousemove);
49414
49415         select(document)
49416             .call(keybinding);
49417
49418         return draw;
49419     }
49420
49421
49422     draw.off = function(selection$$1) {
49423         context.ui().sidebar.hover.cancel();
49424         context.uninstall(hover);
49425         context.uninstall(edit);
49426
49427         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49428             context.uninstall(tail);
49429             cached.usedTails[tail.text()] = true;
49430         }
49431
49432         selection$$1
49433             .on('mouseenter.draw', null)
49434             .on('mouseleave.draw', null)
49435             .on('mousedown.draw', null)
49436             .on('mousemove.draw', null);
49437
49438         select(window)
49439             .on('mouseup.draw', null);
49440             // note: keyup.space-block, click.draw-block should remain
49441
49442         select(document)
49443             .call(keybinding.off);
49444     };
49445
49446
49447     draw.tail = function(_) {
49448         tail.text(_);
49449         return draw;
49450     };
49451
49452
49453     return utilRebind(draw, dispatch$$1, 'on');
49454 }
49455
49456 function behaviorAddWay(context) {
49457     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
49458         draw = behaviorDraw(context);
49459
49460     var addWay = function(surface) {
49461         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
49462             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
49463             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
49464             .on('cancel', addWay.cancel)
49465             .on('finish', addWay.cancel);
49466
49467         context.map()
49468             .dblclickEnable(false);
49469
49470         surface.call(draw);
49471     };
49472
49473
49474     addWay.off = function(surface) {
49475         surface.call(draw.off);
49476     };
49477
49478
49479     addWay.cancel = function() {
49480         window.setTimeout(function() {
49481             context.map().dblclickEnable(true);
49482         }, 1000);
49483
49484         context.enter(modeBrowse(context));
49485     };
49486
49487
49488     addWay.tail = function(text$$1) {
49489         draw.tail(text$$1);
49490         return addWay;
49491     };
49492
49493
49494     return utilRebind(addWay, dispatch$$1, 'on');
49495 }
49496
49497 function behaviorBreathe() {
49498     var duration = 800,
49499         steps = 4,
49500         selector$$1 = '.selected.shadow, .selected .shadow',
49501         selected = select(null),
49502         classed = '',
49503         params = {},
49504         done = false,
49505         timer$$1;
49506
49507
49508     function ratchetyInterpolator(a, b, steps, units) {
49509         a = parseFloat(a);
49510         b = parseFloat(b);
49511         var sample = quantize$2()
49512             .domain([0, 1])
49513             .range(quantize$1(number$1(a, b), steps));
49514
49515         return function(t) {
49516             return String(sample(t)) + (units || '');
49517         };
49518     }
49519
49520
49521     function reset(selection$$1) {
49522         selection$$1
49523             .style('stroke-opacity', null)
49524             .style('stroke-width', null)
49525             .style('fill-opacity', null)
49526             .style('r', null);
49527     }
49528
49529
49530     function setAnimationParams(transition$$1, fromTo) {
49531         var toFrom = (fromTo === 'from' ? 'to' : 'from');
49532
49533         transition$$1
49534             .styleTween('stroke-opacity', function(d) {
49535                 return ratchetyInterpolator(
49536                     params[d.id][toFrom].opacity,
49537                     params[d.id][fromTo].opacity,
49538                     steps
49539                 );
49540             })
49541             .styleTween('stroke-width', function(d) {
49542                 return ratchetyInterpolator(
49543                     params[d.id][toFrom].width,
49544                     params[d.id][fromTo].width,
49545                     steps,
49546                     'px'
49547                 );
49548             })
49549             .styleTween('fill-opacity', function(d) {
49550                 return ratchetyInterpolator(
49551                     params[d.id][toFrom].opacity,
49552                     params[d.id][fromTo].opacity,
49553                     steps
49554                 );
49555             })
49556             .styleTween('r', function(d) {
49557                 return ratchetyInterpolator(
49558                     params[d.id][toFrom].width,
49559                     params[d.id][fromTo].width,
49560                     steps,
49561                     'px'
49562                 );
49563             });
49564     }
49565
49566
49567     function calcAnimationParams(selection$$1) {
49568         selection$$1
49569             .call(reset)
49570             .each(function(d) {
49571                 var s = select(this),
49572                     tag = s.node().tagName,
49573                     p = {'from': {}, 'to': {}},
49574                     opacity, width;
49575
49576                 // determine base opacity and width
49577                 if (tag === 'circle') {
49578                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
49579                     width = parseFloat(s.style('r') || 15.5);
49580                 } else {
49581                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49582                     width = parseFloat(s.style('stroke-width') || 10);
49583                 }
49584
49585                 // calculate from/to interpolation params..
49586                 p.tag = tag;
49587                 p.from.opacity = opacity * 0.6;
49588                 p.to.opacity = opacity * 1.25;
49589                 p.from.width = width * 0.9;
49590                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
49591                 params[d.id] = p;
49592             });
49593     }
49594
49595
49596     function run(surface, fromTo) {
49597         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49598             currSelected = surface.selectAll(selector$$1),
49599             currClassed = surface.attr('class');
49600
49601         if (done || currSelected.empty()) {
49602             selected.call(reset);
49603             return;
49604         }
49605
49606         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49607             selected.call(reset);
49608             classed = currClassed;
49609             selected = currSelected.call(calcAnimationParams);
49610         }
49611
49612         selected
49613             .transition()
49614             .duration(duration)
49615             .call(setAnimationParams, fromTo)
49616             .on('end', function() {
49617                 surface.call(run, toFrom);
49618             });
49619     }
49620
49621
49622     var breathe = function(surface) {
49623         done = false;
49624         timer$$1 = timer$1(function() {
49625             // wait for elements to actually become selected
49626             if (surface.selectAll(selector$$1).empty()) {
49627                 return false;
49628             }
49629
49630             surface.call(run, 'from');
49631             timer$$1.stop();
49632             return true;
49633         }, 20);
49634     };
49635
49636
49637     breathe.off = function() {
49638         done = true;
49639         if (timer$$1) {
49640             timer$$1.stop();
49641         }
49642         selected
49643             .interrupt()
49644             .call(reset);
49645     };
49646
49647
49648     return breathe;
49649 }
49650
49651 function behaviorCopy(context) {
49652     var keybinding = d3keybinding('copy');
49653
49654
49655     function groupEntities(ids, graph) {
49656         var entities = ids.map(function (id) { return graph.entity(id); });
49657         return lodash.extend({relation: [], way: [], node: []},
49658             lodash.groupBy(entities, function(entity) { return entity.type; }));
49659     }
49660
49661
49662     function getDescendants(id, graph, descendants) {
49663         var entity = graph.entity(id),
49664             i, children;
49665
49666         descendants = descendants || {};
49667
49668         if (entity.type === 'relation') {
49669             children = lodash.map(entity.members, 'id');
49670         } else if (entity.type === 'way') {
49671             children = entity.nodes;
49672         } else {
49673             children = [];
49674         }
49675
49676         for (i = 0; i < children.length; i++) {
49677             if (!descendants[children[i]]) {
49678                 descendants[children[i]] = true;
49679                 descendants = getDescendants(children[i], graph, descendants);
49680             }
49681         }
49682
49683         return descendants;
49684     }
49685
49686
49687     function doCopy() {
49688         event.preventDefault();
49689         if (context.inIntro()) return;
49690
49691         var graph = context.graph(),
49692             selected = groupEntities(context.selectedIDs(), graph),
49693             canCopy = [],
49694             skip = {},
49695             i, entity;
49696
49697         for (i = 0; i < selected.relation.length; i++) {
49698             entity = selected.relation[i];
49699             if (!skip[entity.id] && entity.isComplete(graph)) {
49700                 canCopy.push(entity.id);
49701                 skip = getDescendants(entity.id, graph, skip);
49702             }
49703         }
49704         for (i = 0; i < selected.way.length; i++) {
49705             entity = selected.way[i];
49706             if (!skip[entity.id]) {
49707                 canCopy.push(entity.id);
49708                 skip = getDescendants(entity.id, graph, skip);
49709             }
49710         }
49711         for (i = 0; i < selected.node.length; i++) {
49712             entity = selected.node[i];
49713             if (!skip[entity.id]) {
49714                 canCopy.push(entity.id);
49715             }
49716         }
49717
49718         context.copyIDs(canCopy);
49719     }
49720
49721
49722     function copy() {
49723         keybinding.on(uiCmd('⌘C'), doCopy);
49724         select(document).call(keybinding);
49725         return copy;
49726     }
49727
49728
49729     copy.off = function() {
49730         select(document).call(keybinding.off);
49731     };
49732
49733
49734     return copy;
49735 }
49736
49737 /*
49738     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49739
49740     * The `origin` function is expected to return an [x, y] tuple rather than an
49741       {x, y} object.
49742     * The events are `start`, `move`, and `end`.
49743       (https://github.com/mbostock/d3/issues/563)
49744     * The `start` event is not dispatched until the first cursor movement occurs.
49745       (https://github.com/mbostock/d3/pull/368)
49746     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49747       than `x`, `y`, `dx`, and `dy` properties.
49748     * The `end` event is not dispatched if no movement occurs.
49749     * An `off` function is available that unbinds the drag's internal event handlers.
49750     * Delegation is supported via the `delegate` function.
49751
49752  */
49753 function behaviorDrag() {
49754     var event$$1 = dispatch('start', 'move', 'end'),
49755         origin = null,
49756         selector$$1 = '',
49757         filter = null,
49758         event_, target, surface;
49759
49760
49761     function d3_eventCancel() {
49762         event.stopPropagation();
49763         event.preventDefault();
49764     }
49765
49766     function eventOf(thiz, argumentz) {
49767         return function(e1) {
49768             e1.target = drag$$1;
49769             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49770         };
49771     }
49772
49773     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49774         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49775             function () {
49776                 var selection$$1 = selection(),
49777                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49778                 selection$$1.style(d3_event_userSelectProperty, 'none');
49779                 return function () {
49780                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49781                 };
49782             } :
49783             function (type) {
49784                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49785                 return function () {
49786                     w.on('selectstart.' + type, null);
49787                 };
49788             };
49789
49790
49791     function dragstart() {
49792         target = this;
49793         event_ = eventOf(target, arguments);
49794
49795         var eventTarget = event.target,
49796             touchId = event.touches ? event.changedTouches[0].identifier : null,
49797             offset,
49798             origin_ = point(),
49799             started = false,
49800             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49801
49802         var w = select(window)
49803             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49804             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49805
49806         if (origin) {
49807             offset = origin.apply(target, arguments);
49808             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49809         } else {
49810             offset = [0, 0];
49811         }
49812
49813         if (touchId === null) event.stopPropagation();
49814
49815
49816         function point() {
49817             var p = surface || target.parentNode;
49818             return touchId !== null ? touches(p).filter(function(p) {
49819                 return p.identifier === touchId;
49820             })[0] : mouse(p);
49821         }
49822
49823
49824         function dragmove() {
49825             var p = point(),
49826                 dx = p[0] - origin_[0],
49827                 dy = p[1] - origin_[1];
49828
49829             if (dx === 0 && dy === 0)
49830                 return;
49831
49832             if (!started) {
49833                 started = true;
49834                 event_({
49835                     type: 'start'
49836                 });
49837             }
49838
49839             origin_ = p;
49840             d3_eventCancel();
49841
49842             event_({
49843                 type: 'move',
49844                 point: [p[0] + offset[0],  p[1] + offset[1]],
49845                 delta: [dx, dy]
49846             });
49847         }
49848
49849
49850         function dragend() {
49851             if (started) {
49852                 event_({
49853                     type: 'end'
49854                 });
49855
49856                 d3_eventCancel();
49857                 if (event.target === eventTarget) w.on('click.drag', click, true);
49858             }
49859
49860             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49861                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49862             selectEnable();
49863         }
49864
49865
49866         function click() {
49867             d3_eventCancel();
49868             w.on('click.drag', null);
49869         }
49870     }
49871
49872
49873     function drag$$1(selection$$1) {
49874         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49875             delegate = dragstart;
49876
49877         if (selector$$1) {
49878             delegate = function() {
49879                 var root = this,
49880                     target = event.target;
49881                 for (; target && target !== root; target = target.parentNode) {
49882                     if (target[matchesSelector](selector$$1) &&
49883                             (!filter || filter(target.__data__))) {
49884                         return dragstart.call(target, target.__data__);
49885                     }
49886                 }
49887             };
49888         }
49889
49890         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49891             .on('touchstart.drag' + selector$$1, delegate);
49892     }
49893
49894
49895     drag$$1.off = function(selection$$1) {
49896         selection$$1.on('mousedown.drag' + selector$$1, null)
49897             .on('touchstart.drag' + selector$$1, null);
49898     };
49899
49900
49901     drag$$1.delegate = function(_) {
49902         if (!arguments.length) return selector$$1;
49903         selector$$1 = _;
49904         return drag$$1;
49905     };
49906
49907
49908     drag$$1.filter = function(_) {
49909         if (!arguments.length) return origin;
49910         filter = _;
49911         return drag$$1;
49912     };
49913
49914
49915     drag$$1.origin = function (_) {
49916         if (!arguments.length) return origin;
49917         origin = _;
49918         return drag$$1;
49919     };
49920
49921
49922     drag$$1.cancel = function() {
49923         select(window)
49924             .on('mousemove.drag', null)
49925             .on('mouseup.drag', null);
49926         return drag$$1;
49927     };
49928
49929
49930     drag$$1.target = function() {
49931         if (!arguments.length) return target;
49932         target = arguments[0];
49933         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49934         return drag$$1;
49935     };
49936
49937
49938     drag$$1.surface = function() {
49939         if (!arguments.length) return surface;
49940         surface = arguments[0];
49941         return drag$$1;
49942     };
49943
49944
49945     return utilRebind(drag$$1, event$$1, 'on');
49946 }
49947
49948 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49949
49950     var way = context.entity(wayId),
49951         isArea = context.geometry(wayId) === 'area',
49952         finished = false,
49953         annotation = t((way.isDegenerate() ?
49954             'operations.start.annotation.' :
49955             'operations.continue.annotation.') + context.geometry(wayId)),
49956         draw = behaviorDraw(context),
49957         startIndex, start, end, segment;
49958
49959
49960     if (!isArea) {
49961         startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0;
49962         start = osmNode({ id: 'nStart', loc: context.entity(way.nodes[startIndex]).loc });
49963         end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
49964         segment = osmWay({ id: 'wTemp',
49965             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49966             tags: lodash.clone(way.tags)
49967         });
49968     } else {
49969         end = osmNode({ loc: context.map().mouseCoordinates() });
49970     }
49971
49972
49973     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49974     if (isArea) {
49975         fn(actionAddEntity(end),
49976             actionAddVertex(wayId, end.id)
49977         );
49978     } else {
49979         fn(actionAddEntity(start),
49980             actionAddEntity(end),
49981             actionAddEntity(segment)
49982         );
49983     }
49984
49985
49986     function move(datum) {
49987         var loc;
49988
49989         if (datum.type === 'node' && datum.id !== end.id) {
49990             loc = datum.loc;
49991
49992         } else if (datum.type === 'way') { // && (segment || datum.id !== segment.id)) {
49993             var dims = context.map().dimensions(),
49994                 mouse = context.mouse(),
49995                 pad = 5,
49996                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49997                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49998
49999             if (trySnap) {
50000                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
50001             }
50002         }
50003
50004         if (!loc) {
50005             loc = context.map().mouseCoordinates();
50006         }
50007
50008         context.replace(actionMoveNode(end.id, loc));
50009     }
50010
50011
50012     function undone() {
50013         finished = true;
50014         context.enter(modeBrowse(context));
50015     }
50016
50017
50018     function setActiveElements() {
50019         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
50020         context.surface().selectAll(utilEntitySelector(active))
50021             .classed('active', true);
50022     }
50023
50024
50025     var drawWay = function(surface) {
50026         draw.on('move', move)
50027             .on('click', drawWay.add)
50028             .on('clickWay', drawWay.addWay)
50029             .on('clickNode', drawWay.addNode)
50030             .on('undo', context.undo)
50031             .on('cancel', drawWay.cancel)
50032             .on('finish', drawWay.finish);
50033
50034         context.map()
50035             .dblclickEnable(false)
50036             .on('drawn.draw', setActiveElements);
50037
50038         setActiveElements();
50039
50040         surface.call(draw);
50041
50042         context.history()
50043             .on('undone.draw', undone);
50044     };
50045
50046
50047     drawWay.off = function(surface) {
50048         if (!finished)
50049             context.pop();
50050
50051         context.map()
50052             .on('drawn.draw', null);
50053
50054         surface.call(draw.off)
50055             .selectAll('.active')
50056             .classed('active', false);
50057
50058         context.history()
50059             .on('undone.draw', null);
50060     };
50061
50062
50063     function ReplaceTemporaryNode(newNode) {
50064         return function(graph) {
50065             if (isArea) {
50066                 return graph
50067                     .replace(way.addNode(newNode.id))
50068                     .remove(end);
50069             } else {
50070                 return graph
50071                     .replace(graph.entity(wayId).addNode(newNode.id, index))
50072                     .remove(end)
50073                     .remove(segment)
50074                     .remove(start);
50075             }
50076         };
50077     }
50078
50079
50080     // Accept the current position of the temporary node and continue drawing.
50081     drawWay.add = function(loc) {
50082         // prevent duplicate nodes
50083         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
50084         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
50085
50086         if (isArea) {
50087             context.replace(
50088                 actionMoveNode(end.id, loc),
50089                 annotation
50090             );
50091         } else {
50092             var newNode = osmNode({loc: loc});
50093             context.replace(
50094                 actionAddEntity(newNode),
50095                 ReplaceTemporaryNode(newNode),
50096                 annotation
50097             );
50098         }
50099
50100         finished = true;
50101         context.enter(mode);
50102     };
50103
50104
50105     // Connect the way to an existing way.
50106     drawWay.addWay = function(loc, edge) {
50107
50108         if (isArea) {
50109             context.perform(
50110                 actionAddMidpoint({ loc: loc, edge: edge}, end),
50111                 annotation
50112             );
50113         } else {
50114             var previousEdge = startIndex ?
50115                 [way.nodes[startIndex], way.nodes[startIndex - 1]] :
50116                 [way.nodes[0], way.nodes[1]];
50117
50118             // Avoid creating duplicate segments
50119             if (geoEdgeEqual(edge, previousEdge))
50120                 return;
50121
50122             var newNode = osmNode({ loc: loc });
50123             context.perform(
50124                 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
50125                 ReplaceTemporaryNode(newNode),
50126                 annotation
50127             );
50128         }
50129
50130         finished = true;
50131         context.enter(mode);
50132     };
50133
50134
50135     // Connect the way to an existing node and continue drawing.
50136     drawWay.addNode = function(node) {
50137         // Avoid creating duplicate segments
50138         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
50139
50140         context.perform(
50141             ReplaceTemporaryNode(node),
50142             annotation
50143         );
50144
50145         finished = true;
50146         context.enter(mode);
50147     };
50148
50149
50150     // Finish the draw operation, removing the temporary node. If the way has enough
50151     // nodes to be valid, it's selected. Otherwise, return to browse mode.
50152     drawWay.finish = function() {
50153         context.pop();
50154         finished = true;
50155
50156         window.setTimeout(function() {
50157             context.map().dblclickEnable(true);
50158         }, 1000);
50159
50160         if (context.hasEntity(wayId)) {
50161             context.enter(
50162                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
50163             );
50164         } else {
50165             context.enter(modeBrowse(context));
50166         }
50167     };
50168
50169
50170     // Cancel the draw operation and return to browse, deleting everything drawn.
50171     drawWay.cancel = function() {
50172         context.perform(
50173             utilFunctor(baseGraph),
50174             t('operations.cancel_draw.annotation'));
50175
50176         window.setTimeout(function() {
50177             context.map().dblclickEnable(true);
50178         }, 1000);
50179
50180         finished = true;
50181         context.enter(modeBrowse(context));
50182     };
50183
50184
50185     drawWay.tail = function(text) {
50186         draw.tail(text);
50187         return drawWay;
50188     };
50189
50190
50191     return drawWay;
50192 }
50193
50194 function behaviorHash(context) {
50195     var s0 = null, // cached window.location.hash
50196         lat = 90 - 1e-8; // allowable latitude range
50197
50198
50199     var parser = function(map$$1, s) {
50200         var q = utilStringQs(s);
50201         var args = (q.map || '').split('/').map(Number);
50202         if (args.length < 3 || args.some(isNaN)) {
50203             return true; // replace bogus hash
50204         } else if (s !== formatter(map$$1).slice(1)) {
50205             map$$1.centerZoom([args[2],
50206                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
50207         }
50208     };
50209
50210
50211     var formatter = function(map$$1) {
50212         var mode = context.mode(),
50213             center = map$$1.center(),
50214             zoom$$1 = map$$1.zoom(),
50215             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
50216             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
50217             newParams = {};
50218
50219         if (mode && mode.id === 'browse') {
50220             delete q.id;
50221         } else {
50222             var selected = context.selectedIDs().filter(function(id) {
50223                 return !context.entity(id).isNew();
50224             });
50225             if (selected.length) {
50226                 newParams.id = selected.join(',');
50227             }
50228         }
50229
50230         newParams.map = zoom$$1.toFixed(2) +
50231                 '/' + center[1].toFixed(precision) +
50232                 '/' + center[0].toFixed(precision);
50233
50234         return '#' + utilQsString(lodash.assign(q, newParams), true);
50235     };
50236
50237
50238     function update() {
50239         if (context.inIntro()) return;
50240         var s1 = formatter(context.map());
50241         if (s0 !== s1) {
50242             window.location.replace(s0 = s1);  // don't recenter the map!
50243         }
50244     }
50245
50246
50247     var throttledUpdate = lodash.throttle(update, 500);
50248
50249
50250     function hashchange() {
50251         if (window.location.hash === s0) return;  // ignore spurious hashchange events
50252         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
50253             update(); // replace bogus hash
50254         }
50255     }
50256
50257
50258     function hash() {
50259         context.map()
50260             .on('move.hash', throttledUpdate);
50261
50262         context
50263             .on('enter.hash', throttledUpdate);
50264
50265         select(window)
50266             .on('hashchange.hash', hashchange);
50267
50268         if (window.location.hash) {
50269             var q = utilStringQs(window.location.hash.substring(1));
50270             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
50271             if (q.comment) context.storage('comment', q.comment);
50272             hashchange();
50273             if (q.map) hash.hadHash = true;
50274         }
50275     }
50276
50277
50278     hash.off = function() {
50279         throttledUpdate.cancel();
50280
50281         context.map()
50282             .on('move.hash', null);
50283
50284         context
50285             .on('enter.hash', null);
50286
50287         select(window)
50288             .on('hashchange.hash', null);
50289
50290         window.location.hash = '';
50291     };
50292
50293
50294     return hash;
50295 }
50296
50297 function behaviorLasso(context) {
50298
50299     var behavior = function(selection$$1) {
50300         var lasso;
50301
50302
50303         function mousedown() {
50304             var button = 0;  // left
50305             if (event.button === button && event.shiftKey === true) {
50306                 lasso = null;
50307
50308                 select(window)
50309                     .on('mousemove.lasso', mousemove)
50310                     .on('mouseup.lasso', mouseup);
50311
50312                 event.stopPropagation();
50313             }
50314         }
50315
50316
50317         function mousemove() {
50318             if (!lasso) {
50319                 lasso = uiLasso(context);
50320                 context.surface().call(lasso);
50321             }
50322
50323             lasso.p(context.mouse());
50324         }
50325
50326
50327         function normalize(a, b) {
50328             return [
50329                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
50330                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
50331         }
50332
50333
50334         function lassoed() {
50335             if (!lasso) return [];
50336
50337             var graph = context.graph(),
50338                 bounds = lasso.extent().map(context.projection.invert),
50339                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
50340
50341             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
50342                 return entity.type === 'node' &&
50343                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
50344                     !context.features().isHidden(entity, graph, entity.geometry(graph));
50345             }), 'id');
50346         }
50347
50348
50349         function mouseup() {
50350             select(window)
50351                 .on('mousemove.lasso', null)
50352                 .on('mouseup.lasso', null);
50353
50354             if (!lasso) return;
50355
50356             var ids = lassoed();
50357             lasso.close();
50358
50359             if (ids.length) {
50360                 context.enter(modeSelect(context, ids));
50361             }
50362         }
50363
50364         selection$$1
50365             .on('mousedown.lasso', mousedown);
50366     };
50367
50368
50369     behavior.off = function(selection$$1) {
50370         selection$$1.on('mousedown.lasso', null);
50371     };
50372
50373
50374     return behavior;
50375 }
50376
50377 /* Creates a keybinding behavior for an operation */
50378 function behaviorOperation(context) {
50379     var which, keybinding;
50380
50381
50382     var behavior = function () {
50383         if (which) {
50384             keybinding = d3keybinding('behavior.key.' + which.id);
50385             keybinding.on(which.keys, function() {
50386                 event.preventDefault();
50387                 if (which.available() && !which.disabled() && !context.inIntro()) {
50388                     which();
50389                 }
50390             });
50391             select(document).call(keybinding);
50392         }
50393         return behavior;
50394     };
50395
50396
50397     behavior.off = function() {
50398         if (keybinding) {
50399             select(document).call(keybinding.off);
50400         }
50401     };
50402
50403
50404     behavior.which = function (_) {
50405         if (!arguments.length) return which;
50406         which = _;
50407         return behavior;
50408     };
50409
50410
50411     return behavior;
50412 }
50413
50414 function behaviorPaste(context) {
50415     var keybinding = d3keybinding('paste');
50416
50417     function omitTag(v, k) {
50418         return (
50419             k === 'phone' ||
50420             k === 'fax' ||
50421             k === 'email' ||
50422             k === 'website' ||
50423             k === 'url' ||
50424             k === 'note' ||
50425             k === 'description' ||
50426             k.indexOf('name') !== -1 ||
50427             k.indexOf('wiki') === 0 ||
50428             k.indexOf('addr:') === 0 ||
50429             k.indexOf('contact:') === 0
50430         );
50431     }
50432
50433
50434     function doPaste() {
50435         event.preventDefault();
50436         if (context.inIntro()) return;
50437
50438         var baseGraph = context.graph(),
50439             mouse$$1 = context.mouse(),
50440             projection = context.projection,
50441             viewport = geoExtent$$1(projection.clipExtent()).polygon();
50442
50443         if (!geoPointInPolygon(mouse$$1, viewport)) return;
50444
50445         var extent$$1 = geoExtent$$1(),
50446             oldIDs = context.copyIDs(),
50447             oldGraph = context.copyGraph(),
50448             newIDs = [];
50449
50450         if (!oldIDs.length) return;
50451
50452         var action = actionCopyEntities(oldIDs, oldGraph);
50453         context.perform(action);
50454
50455         var copies = action.copies();
50456         var originals = lodash.invert(lodash.mapValues(copies, 'id'));
50457         for (var id in copies) {
50458             var oldEntity = oldGraph.entity(id),
50459                 newEntity = copies[id];
50460
50461             extent$$1._extend(oldEntity.extent(oldGraph));
50462             context.perform(
50463                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
50464             );
50465
50466             // Exclude child nodes from newIDs if their parent way was also copied.
50467             var parents = context.graph().parentWays(newEntity),
50468                 parentCopied = false;
50469             for (var i = 0; i < parents.length; i++) {
50470                 if (originals[parents[i].id]) {
50471                     parentCopied = true;
50472                     break;
50473                 }
50474             }
50475
50476             if (!parentCopied) {
50477                 newIDs.push(newEntity.id);
50478             }
50479         }
50480
50481         // Put pasted objects where mouse pointer is..
50482         var center = projection(extent$$1.center()),
50483             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
50484
50485         context.perform(actionMove(newIDs, delta, projection));
50486         context.enter(modeMove$$1(context, newIDs, baseGraph));
50487     }
50488
50489
50490     function paste() {
50491         keybinding.on(uiCmd('⌘V'), doPaste);
50492         select(document).call(keybinding);
50493         return paste;
50494     }
50495
50496
50497     paste.off = function() {
50498         select(document).call(keybinding.off);
50499     };
50500
50501
50502     return paste;
50503 }
50504
50505 function behaviorSelect(context) {
50506
50507     function keydown() {
50508         if (event && event.shiftKey) {
50509             context.surface()
50510                 .classed('behavior-multiselect', true);
50511         }
50512     }
50513
50514
50515     function keyup() {
50516         if (!event || !event.shiftKey) {
50517             context.surface()
50518                 .classed('behavior-multiselect', false);
50519         }
50520     }
50521
50522
50523     function click() {
50524         var datum = event.target.__data__,
50525             lasso = select('#surface .lasso').node(),
50526             mode = context.mode();
50527
50528         if (datum.type === 'midpoint') {
50529             // do nothing
50530         } else if (!(datum instanceof osmEntity$$1)) {
50531             if (!event.shiftKey && !lasso && mode.id !== 'browse')
50532                 context.enter(modeBrowse(context));
50533
50534         } else if (!event.shiftKey && !lasso) {
50535             // Avoid re-entering Select mode with same entity.
50536             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
50537                 context.enter(modeSelect(context, [datum.id]));
50538             } else {
50539                 mode.suppressMenu(false).reselect();
50540             }
50541         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
50542             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
50543             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
50544
50545         } else {
50546             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
50547         }
50548     }
50549
50550
50551     var behavior = function(selection$$1) {
50552         select(window)
50553             .on('keydown.select', keydown)
50554             .on('keyup.select', keyup);
50555
50556         selection$$1.on('click.select', click);
50557
50558         keydown();
50559     };
50560
50561
50562     behavior.off = function(selection$$1) {
50563         select(window)
50564             .on('keydown.select', null)
50565             .on('keyup.select', null);
50566
50567         selection$$1.on('click.select', null);
50568
50569         keyup();
50570     };
50571
50572
50573     return behavior;
50574 }
50575
50576 function modeAddArea$$1(context) {
50577     var mode = {
50578         id: 'add-area',
50579         button: 'area',
50580         title: t('modes.add_area.title'),
50581         description: t('modes.add_area.description'),
50582         key: '3'
50583     };
50584
50585     var behavior = behaviorAddWay(context)
50586             .tail(t('modes.add_area.tail'))
50587             .on('start', start)
50588             .on('startFromWay', startFromWay)
50589             .on('startFromNode', startFromNode),
50590         defaultTags = { area: 'yes' };
50591
50592
50593     function actionClose(wayId) {
50594         return function (graph) {
50595             return graph.replace(graph.entity(wayId).close());
50596         };
50597     }
50598
50599
50600     function start(loc) {
50601         var graph = context.graph(),
50602             node = osmNode({ loc: loc }),
50603             way = osmWay({ tags: defaultTags });
50604
50605         context.perform(
50606             actionAddEntity(node),
50607             actionAddEntity(way),
50608             actionAddVertex(way.id, node.id),
50609             actionClose(way.id)
50610         );
50611
50612         context.enter(modeDrawArea(context, way.id, graph));
50613     }
50614
50615
50616     function startFromWay(loc, edge) {
50617         var graph = context.graph(),
50618             node = osmNode({ loc: loc }),
50619             way = osmWay({ tags: defaultTags });
50620
50621         context.perform(
50622             actionAddEntity(node),
50623             actionAddEntity(way),
50624             actionAddVertex(way.id, node.id),
50625             actionClose(way.id),
50626             actionAddMidpoint({ loc: loc, edge: edge }, node)
50627         );
50628
50629         context.enter(modeDrawArea(context, way.id, graph));
50630     }
50631
50632
50633     function startFromNode(node) {
50634         var graph = context.graph(),
50635             way = osmWay({ tags: defaultTags });
50636
50637         context.perform(
50638             actionAddEntity(way),
50639             actionAddVertex(way.id, node.id),
50640             actionClose(way.id)
50641         );
50642
50643         context.enter(modeDrawArea(context, way.id, graph));
50644     }
50645
50646
50647     mode.enter = function() {
50648         context.install(behavior);
50649     };
50650
50651
50652     mode.exit = function() {
50653         context.uninstall(behavior);
50654     };
50655
50656
50657     return mode;
50658 }
50659
50660 function modeAddLine$$1(context) {
50661     var mode = {
50662         id: 'add-line',
50663         button: 'line',
50664         title: t('modes.add_line.title'),
50665         description: t('modes.add_line.description'),
50666         key: '2'
50667     };
50668
50669     var behavior = behaviorAddWay(context)
50670         .tail(t('modes.add_line.tail'))
50671         .on('start', start)
50672         .on('startFromWay', startFromWay)
50673         .on('startFromNode', startFromNode);
50674
50675
50676     function start(loc) {
50677         var baseGraph = context.graph(),
50678             node = osmNode({ loc: loc }),
50679             way = osmWay();
50680
50681         context.perform(
50682             actionAddEntity(node),
50683             actionAddEntity(way),
50684             actionAddVertex(way.id, node.id)
50685         );
50686
50687         context.enter(modeDrawLine(context, way.id, baseGraph));
50688     }
50689
50690
50691     function startFromWay(loc, edge) {
50692         var baseGraph = context.graph(),
50693             node = osmNode({ loc: loc }),
50694             way = osmWay();
50695
50696         context.perform(
50697             actionAddEntity(node),
50698             actionAddEntity(way),
50699             actionAddVertex(way.id, node.id),
50700             actionAddMidpoint({ loc: loc, edge: edge }, node)
50701         );
50702
50703         context.enter(modeDrawLine(context, way.id, baseGraph));
50704     }
50705
50706
50707     function startFromNode(node) {
50708         var baseGraph = context.graph(),
50709             way = osmWay();
50710
50711         context.perform(
50712             actionAddEntity(way),
50713             actionAddVertex(way.id, node.id)
50714         );
50715
50716         context.enter(modeDrawLine(context, way.id, baseGraph));
50717     }
50718
50719
50720     mode.enter = function() {
50721         context.install(behavior);
50722     };
50723
50724
50725     mode.exit = function() {
50726         context.uninstall(behavior);
50727     };
50728
50729     return mode;
50730 }
50731
50732 function modeAddPoint$$1(context) {
50733     var mode = {
50734         id: 'add-point',
50735         button: 'point',
50736         title: t('modes.add_point.title'),
50737         description: t('modes.add_point.description'),
50738         key: '1'
50739     };
50740
50741     var behavior = behaviorDraw(context)
50742         .tail(t('modes.add_point.tail'))
50743         .on('click', add)
50744         .on('clickWay', addWay)
50745         .on('clickNode', addNode)
50746         .on('cancel', cancel)
50747         .on('finish', cancel);
50748
50749
50750     function add(loc) {
50751         var node = osmNode({ loc: loc });
50752
50753         context.perform(
50754             actionAddEntity(node),
50755             t('operations.add.annotation.point')
50756         );
50757
50758         context.enter(
50759             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50760         );
50761     }
50762
50763
50764     function addWay(loc) {
50765         add(loc);
50766     }
50767
50768
50769     function addNode(node) {
50770         add(node.loc);
50771     }
50772
50773
50774     function cancel() {
50775         context.enter(modeBrowse(context));
50776     }
50777
50778
50779     mode.enter = function() {
50780         context.install(behavior);
50781     };
50782
50783
50784     mode.exit = function() {
50785         context.uninstall(behavior);
50786     };
50787
50788
50789     return mode;
50790 }
50791
50792 function modeBrowse(context) {
50793     var mode = {
50794         button: 'browse',
50795         id: 'browse',
50796         title: t('modes.browse.title'),
50797         description: t('modes.browse.description')
50798     }, sidebar;
50799
50800     var behaviors = [
50801         behaviorPaste(context),
50802         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50803         behaviorSelect(context),
50804         behaviorLasso(context)
50805     ];
50806
50807
50808     mode.enter = function() {
50809         behaviors.forEach(function(behavior) {
50810             context.install(behavior);
50811         });
50812
50813         // Get focus on the body.
50814         if (document.activeElement && document.activeElement.blur) {
50815             document.activeElement.blur();
50816         }
50817
50818         if (sidebar) {
50819             context.ui().sidebar.show(sidebar);
50820         } else {
50821             context.ui().sidebar.select(null);
50822         }
50823     };
50824
50825
50826     mode.exit = function() {
50827         context.ui().sidebar.hover.cancel();
50828         behaviors.forEach(function(behavior) {
50829             context.uninstall(behavior);
50830         });
50831
50832         if (sidebar) {
50833             context.ui().sidebar.hide();
50834         }
50835     };
50836
50837
50838     mode.sidebar = function(_) {
50839         if (!arguments.length) return sidebar;
50840         sidebar = _;
50841         return mode;
50842     };
50843
50844
50845     return mode;
50846 }
50847
50848 function modeDragNode$$1(context) {
50849     var mode = {
50850         id: 'drag-node',
50851         button: 'browse'
50852     };
50853
50854     var nudgeInterval,
50855         activeIDs,
50856         wasMidpoint,
50857         isCancelled,
50858         lastLoc,
50859         selectedIDs = [],
50860         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50861         edit = behaviorEdit(context);
50862
50863
50864     function vecSub(a, b) {
50865         return [a[0] - b[0], a[1] - b[1]];
50866     }
50867
50868     function edge(point, size) {
50869         var pad = [30, 100, 30, 100],
50870             x = 0,
50871             y = 0;
50872
50873         if (point[0] > size[0] - pad[0])
50874             x = -10;
50875         if (point[0] < pad[2])
50876             x = 10;
50877         if (point[1] > size[1] - pad[1])
50878             y = -10;
50879         if (point[1] < pad[3])
50880             y = 10;
50881
50882         if (x || y) {
50883             return [x, y];
50884         } else {
50885             return null;
50886         }
50887     }
50888
50889
50890     function startNudge(entity, nudge) {
50891         if (nudgeInterval) window.clearInterval(nudgeInterval);
50892         nudgeInterval = window.setInterval(function() {
50893             context.pan(nudge);
50894             doMove(entity, nudge);
50895         }, 50);
50896     }
50897
50898
50899     function stopNudge() {
50900         if (nudgeInterval) window.clearInterval(nudgeInterval);
50901         nudgeInterval = null;
50902     }
50903
50904
50905     function moveAnnotation(entity) {
50906         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50907     }
50908
50909
50910     function connectAnnotation(entity) {
50911         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50912     }
50913
50914
50915     function origin(entity) {
50916         return context.projection(entity.loc);
50917     }
50918
50919
50920     function start(entity) {
50921         wasMidpoint = entity.type === 'midpoint';
50922
50923         // Things allowed to be dragged include:
50924         // - midpoints
50925         // - nodes that are selected
50926         // - vertices that are selected
50927         // - vertices classed 'sibling' which includes (see svg/vertices.js)
50928         //   - children of selected ways or multipolygons
50929         //   - vertices sharing a way with selected vertices
50930         var selector$$1 = 'g.node.point.selected.' + entity.id +
50931             ', g.vertex-persistent.selected.' + entity.id +
50932             ', g.vertex-persistent.sibling.' + entity.id;
50933
50934         var isDraggable = wasMidpoint || !select(selector$$1).empty();
50935
50936         isCancelled = event.sourceEvent.shiftKey || !isDraggable ||
50937             context.features().hasHiddenConnections(entity, context.graph());
50938
50939         if (isCancelled) {
50940             return behavior.cancel();
50941         }
50942
50943         if (wasMidpoint) {
50944             var midpoint = entity;
50945             entity = osmNode();
50946             context.perform(actionAddMidpoint(midpoint, entity));
50947
50948             var vertex = context.surface().selectAll('.' + entity.id);
50949             behavior.target(vertex.node(), entity);
50950
50951         } else {
50952             context.perform(actionNoop());
50953         }
50954
50955         // activeIDs generate no pointer events.  This prevents the node or vertex
50956         // being dragged from trying to connect to itself or its parent element.
50957         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50958         activeIDs.push(entity.id);
50959         setActiveElements();
50960
50961         context.enter(mode);
50962     }
50963
50964
50965     function datum() {
50966         var event$$1 = event && event.sourceEvent;
50967         if (!event$$1 || event$$1.altKey) {
50968             return {};
50969         } else {
50970             return event$$1.target.__data__ || {};
50971         }
50972     }
50973
50974
50975     function doMove(entity, nudge) {
50976         nudge = nudge || [0, 0];
50977
50978         var currPoint = (event && event.point) || context.projection(lastLoc),
50979             currMouse = vecSub(currPoint, nudge),
50980             loc = context.projection.invert(currMouse),
50981             d = datum();
50982
50983         if (d.type === 'node' && d.id !== entity.id) {
50984             loc = d.loc;
50985         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50986             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50987         }
50988
50989         context.replace(
50990             actionMoveNode(entity.id, loc),
50991             moveAnnotation(entity)
50992         );
50993
50994         lastLoc = loc;
50995     }
50996
50997
50998     function move(entity) {
50999         if (isCancelled) return;
51000         event.sourceEvent.stopPropagation();
51001         lastLoc = context.projection.invert(event.point);
51002
51003         doMove(entity);
51004         var nudge = edge(event.point, context.map().dimensions());
51005         if (nudge) startNudge(entity, nudge);
51006         else stopNudge();
51007     }
51008
51009
51010     function end(entity) {
51011         if (isCancelled) return;
51012
51013         var d = datum();
51014
51015         if (d.type === 'way') {
51016             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
51017             context.replace(
51018                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
51019                 connectAnnotation(d)
51020             );
51021
51022         } else if (d.type === 'node' && d.id !== entity.id) {
51023             context.replace(
51024                 actionConnect([d.id, entity.id]),
51025                 connectAnnotation(d)
51026             );
51027
51028         } else if (wasMidpoint) {
51029             context.replace(
51030                 actionNoop(),
51031                 t('operations.add.annotation.vertex')
51032             );
51033
51034         } else {
51035             context.replace(
51036                 actionNoop(),
51037                 moveAnnotation(entity)
51038             );
51039         }
51040
51041         var reselection = selectedIDs.filter(function(id) {
51042             return context.graph().hasEntity(id);
51043         });
51044
51045         if (reselection.length) {
51046             context.enter(modeSelect(context, reselection).suppressMenu(true));
51047         } else {
51048             context.enter(modeBrowse(context));
51049         }
51050     }
51051
51052
51053     function cancel() {
51054         behavior.cancel();
51055         context.enter(modeBrowse(context));
51056     }
51057
51058
51059     function setActiveElements() {
51060         context.surface().selectAll(utilEntitySelector(activeIDs))
51061             .classed('active', true);
51062     }
51063
51064
51065     var behavior = behaviorDrag()
51066         .delegate('g.node, g.point, g.midpoint')
51067         .surface(select('#map').node())
51068         .origin(origin)
51069         .on('start', start)
51070         .on('move', move)
51071         .on('end', end);
51072
51073
51074     mode.enter = function() {
51075         context.install(hover);
51076         context.install(edit);
51077
51078         context.history()
51079             .on('undone.drag-node', cancel);
51080
51081         context.map()
51082             .on('drawn.drag-node', setActiveElements);
51083
51084         setActiveElements();
51085     };
51086
51087
51088     mode.exit = function() {
51089         context.ui().sidebar.hover.cancel();
51090         context.uninstall(hover);
51091         context.uninstall(edit);
51092
51093         context.history()
51094             .on('undone.drag-node', null);
51095
51096         context.map()
51097             .on('drawn.drag-node', null);
51098
51099         context.surface()
51100             .selectAll('.active')
51101             .classed('active', false);
51102
51103         stopNudge();
51104     };
51105
51106
51107     mode.selectedIDs = function(_) {
51108         if (!arguments.length) return selectedIDs;
51109         selectedIDs = _;
51110         return mode;
51111     };
51112
51113
51114     mode.behavior = behavior;
51115
51116
51117     return mode;
51118 }
51119
51120 function modeDrawArea(context, wayId, baseGraph) {
51121     var mode = {
51122         button: 'area',
51123         id: 'draw-area'
51124     };
51125
51126     var behavior;
51127
51128
51129     mode.enter = function() {
51130         var way = context.entity(wayId);
51131
51132         behavior = behaviorDrawWay(context, wayId, undefined, mode, baseGraph)
51133             .tail(t('modes.draw_area.tail'));
51134
51135         var addNode = behavior.addNode;
51136
51137         behavior.addNode = function(node) {
51138             var length = way.nodes.length,
51139                 penultimate = length > 2 ? way.nodes[length - 2] : null;
51140
51141             if (node.id === way.first() || node.id === penultimate) {
51142                 behavior.finish();
51143             } else {
51144                 addNode(node);
51145             }
51146         };
51147
51148         context.install(behavior);
51149     };
51150
51151
51152     mode.exit = function() {
51153         context.uninstall(behavior);
51154     };
51155
51156
51157     mode.selectedIDs = function() {
51158         return [wayId];
51159     };
51160
51161
51162     return mode;
51163 }
51164
51165 function modeDrawLine(context, wayId, baseGraph, affix) {
51166     var mode = {
51167         button: 'line',
51168         id: 'draw-line'
51169     };
51170
51171     var behavior;
51172
51173
51174     mode.enter = function() {
51175         var way = context.entity(wayId),
51176             index = (affix === 'prefix') ? 0 : undefined,
51177             headId = (affix === 'prefix') ? way.first() : way.last();
51178
51179         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
51180             .tail(t('modes.draw_line.tail'));
51181
51182         var addNode = behavior.addNode;
51183
51184         behavior.addNode = function(node) {
51185             if (node.id === headId) {
51186                 behavior.finish();
51187             } else {
51188                 addNode(node);
51189             }
51190         };
51191
51192         context.install(behavior);
51193     };
51194
51195
51196     mode.exit = function() {
51197         context.uninstall(behavior);
51198     };
51199
51200
51201     mode.selectedIDs = function() {
51202         return [wayId];
51203     };
51204
51205
51206     return mode;
51207 }
51208
51209 function operationCircularize(selectedIDs, context) {
51210     var entityId = selectedIDs[0],
51211         entity = context.entity(entityId),
51212         extent = entity.extent(context.graph()),
51213         geometry = context.geometry(entityId),
51214         action = actionCircularize(entityId, context.projection);
51215
51216
51217     var operation = function() {
51218         context.perform(action, t('operations.circularize.annotation.' + geometry));
51219     };
51220
51221
51222     operation.available = function() {
51223         return selectedIDs.length === 1 &&
51224             entity.type === 'way' &&
51225             lodash.uniq(entity.nodes).length > 1;
51226     };
51227
51228
51229     operation.disabled = function() {
51230         var reason;
51231         if (extent.percentContainedIn(context.extent()) < 0.8) {
51232             reason = 'too_large';
51233         } else if (context.hasHiddenConnections(entityId)) {
51234             reason = 'connected_to_hidden';
51235         }
51236         return action.disabled(context.graph()) || reason;
51237     };
51238
51239
51240     operation.tooltip = function() {
51241         var disable = operation.disabled();
51242         return disable ?
51243             t('operations.circularize.' + disable) :
51244             t('operations.circularize.description.' + geometry);
51245     };
51246
51247
51248     operation.id = 'circularize';
51249     operation.keys = [t('operations.circularize.key')];
51250     operation.title = t('operations.circularize.title');
51251     operation.behavior = behaviorOperation(context).which(operation);
51252
51253     return operation;
51254 }
51255
51256 function operationContinue(selectedIDs, context) {
51257     var graph = context.graph(),
51258         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51259         geometries = lodash.extend({ line: [], vertex: [] },
51260             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51261         vertex = geometries.vertex[0];
51262
51263
51264     function candidateWays() {
51265         return graph.parentWays(vertex).filter(function(parent) {
51266             return parent.geometry(graph) === 'line' &&
51267                 !parent.isClosed() &&
51268                 parent.affix(vertex.id) &&
51269                 (geometries.line.length === 0 || geometries.line[0] === parent);
51270         });
51271     }
51272
51273
51274     var operation = function() {
51275         var candidate = candidateWays()[0];
51276         context.enter(
51277             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51278         );
51279     };
51280
51281
51282     operation.available = function() {
51283         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51284             !context.features().hasHiddenConnections(vertex, context.graph());
51285     };
51286
51287
51288     operation.disabled = function() {
51289         var candidates = candidateWays();
51290         if (candidates.length === 0)
51291             return 'not_eligible';
51292         if (candidates.length > 1)
51293             return 'multiple';
51294     };
51295
51296
51297     operation.tooltip = function() {
51298         var disable = operation.disabled();
51299         return disable ?
51300             t('operations.continue.' + disable) :
51301             t('operations.continue.description');
51302     };
51303
51304
51305     operation.id = 'continue';
51306     operation.keys = [t('operations.continue.key')];
51307     operation.title = t('operations.continue.title');
51308     operation.behavior = behaviorOperation(context).which(operation);
51309
51310     return operation;
51311 }
51312
51313 function operationDelete(selectedIDs, context) {
51314     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51315         action = actionDeleteMultiple(selectedIDs);
51316
51317
51318     var operation = function() {
51319         var annotation,
51320             nextSelectedID;
51321
51322         if (selectedIDs.length > 1) {
51323             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51324
51325         } else {
51326             var id = selectedIDs[0],
51327                 entity = context.entity(id),
51328                 geometry = context.geometry(id),
51329                 parents = context.graph().parentWays(entity),
51330                 parent = parents[0];
51331
51332             annotation = t('operations.delete.annotation.' + geometry);
51333
51334             // Select the next closest node in the way.
51335             if (geometry === 'vertex' && parent.nodes.length > 2) {
51336                 var nodes = parent.nodes,
51337                     i = nodes.indexOf(id);
51338
51339                 if (i === 0) {
51340                     i++;
51341                 } else if (i === nodes.length - 1) {
51342                     i--;
51343                 } else {
51344                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51345                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51346                     i = a < b ? i - 1 : i + 1;
51347                 }
51348
51349                 nextSelectedID = nodes[i];
51350             }
51351         }
51352
51353         context.perform(action, annotation);
51354
51355         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51356             context.enter(
51357                 modeSelect(context, [nextSelectedID]).follow(true).suppressMenu(true)
51358             );
51359         } else {
51360             context.enter(modeBrowse(context));
51361         }
51362
51363     };
51364
51365
51366     operation.available = function() {
51367         return true;
51368     };
51369
51370
51371     operation.disabled = function() {
51372         var reason;
51373         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51374             reason = 'connected_to_hidden';
51375         } else if (lodash.some(selectedIDs, protectedMember)) {
51376             reason = 'part_of_relation';
51377         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51378             reason = 'incomplete_relation';
51379         }
51380         return reason;
51381
51382         function incompleteRelation(id) {
51383             var entity = context.entity(id);
51384             return entity.type === 'relation' && !entity.isComplete(context.graph());
51385         }
51386
51387         function protectedMember(id) {
51388             var entity = context.entity(id);
51389             if (entity.type !== 'way') return false;
51390
51391             var parents = context.graph().parentRelations(entity);
51392             for (var i = 0; i < parents.length; i++) {
51393                 var parent = parents[i],
51394                     type = parent.tags.type,
51395                     role = parent.memberById(id).role || 'outer';
51396                 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
51397                     return true;
51398                 }
51399             }
51400             return false;
51401         }
51402
51403     };
51404
51405
51406     operation.tooltip = function() {
51407         var disable = operation.disabled();
51408         return disable ?
51409             t('operations.delete.' + disable + '.' + multi) :
51410             t('operations.delete.description' + '.' + multi);
51411     };
51412
51413
51414     operation.id = 'delete';
51415     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51416     operation.title = t('operations.delete.title');
51417     operation.behavior = behaviorOperation(context).which(operation);
51418
51419     return operation;
51420 }
51421
51422 function operationDisconnect(selectedIDs, context) {
51423     var vertices = lodash.filter(selectedIDs, function(entityId) {
51424         return context.geometry(entityId) === 'vertex';
51425     });
51426
51427     var entityId = vertices[0],
51428         action = actionDisconnect(entityId);
51429
51430     if (selectedIDs.length > 1) {
51431         action.limitWays(lodash.without(selectedIDs, entityId));
51432     }
51433
51434
51435     var operation = function() {
51436         context.perform(action, t('operations.disconnect.annotation'));
51437     };
51438
51439
51440     operation.available = function() {
51441         return vertices.length === 1;
51442     };
51443
51444
51445     operation.disabled = function() {
51446         var reason;
51447         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51448             reason = 'connected_to_hidden';
51449         }
51450         return action.disabled(context.graph()) || reason;
51451     };
51452
51453
51454     operation.tooltip = function() {
51455         var disable = operation.disabled();
51456         return disable ?
51457             t('operations.disconnect.' + disable) :
51458             t('operations.disconnect.description');
51459     };
51460
51461
51462     operation.id = 'disconnect';
51463     operation.keys = [t('operations.disconnect.key')];
51464     operation.title = t('operations.disconnect.title');
51465     operation.behavior = behaviorOperation(context).which(operation);
51466
51467     return operation;
51468 }
51469
51470 function operationMerge(selectedIDs, context) {
51471     var join = actionJoin(selectedIDs),
51472         merge = actionMerge(selectedIDs),
51473         mergePolygon = actionMergePolygon(selectedIDs);
51474
51475     var operation = function() {
51476         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51477             action;
51478
51479         if (!join.disabled(context.graph())) {
51480             action = join;
51481         } else if (!merge.disabled(context.graph())) {
51482             action = merge;
51483         } else {
51484             action = mergePolygon;
51485         }
51486
51487         context.perform(action, annotation);
51488         var ids = selectedIDs.filter(function(id) {
51489             var entity = context.hasEntity(id);
51490             return entity && entity.type !== 'node';
51491         });
51492         context.enter(modeSelect(context, ids).suppressMenu(true));
51493     };
51494
51495
51496     operation.available = function() {
51497         return selectedIDs.length >= 2;
51498     };
51499
51500
51501     operation.disabled = function() {
51502         return join.disabled(context.graph()) &&
51503             merge.disabled(context.graph()) &&
51504             mergePolygon.disabled(context.graph());
51505     };
51506
51507
51508     operation.tooltip = function() {
51509         var j = join.disabled(context.graph()),
51510             m = merge.disabled(context.graph()),
51511             p = mergePolygon.disabled(context.graph());
51512
51513         if (j === 'restriction' && m && p) {
51514             return t('operations.merge.restriction',
51515                 { relation: context.presets().item('type/restriction').name() });
51516         }
51517
51518         if (p === 'incomplete_relation' && j && m) {
51519             return t('operations.merge.incomplete_relation');
51520         }
51521
51522         if (j && m && p) {
51523             return t('operations.merge.' + j);
51524         }
51525
51526         return t('operations.merge.description');
51527     };
51528
51529
51530     operation.id = 'merge';
51531     operation.keys = [t('operations.merge.key')];
51532     operation.title = t('operations.merge.title');
51533     operation.behavior = behaviorOperation(context).which(operation);
51534
51535     return operation;
51536 }
51537
51538 function operationMove(selectedIDs, context) {
51539     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51540         extent = selectedIDs.reduce(function(extent, id) {
51541             return extent.extend(context.entity(id).extent(context.graph()));
51542         }, geoExtent$$1());
51543
51544
51545     var operation = function() {
51546         context.enter(modeMove$$1(context, selectedIDs));
51547     };
51548
51549
51550     operation.available = function() {
51551         return selectedIDs.length > 1 ||
51552             context.entity(selectedIDs[0]).type !== 'node';
51553     };
51554
51555
51556     operation.disabled = function() {
51557         var reason;
51558         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51559             reason = 'too_large';
51560         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51561             reason = 'connected_to_hidden';
51562         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51563             reason = 'incomplete_relation';
51564         }
51565         return reason;
51566
51567         function incompleteRelation(id) {
51568             var entity = context.entity(id);
51569             return entity.type === 'relation' && !entity.isComplete(context.graph());
51570         }
51571     };
51572
51573
51574     operation.tooltip = function() {
51575         var disable = operation.disabled();
51576         return disable ?
51577             t('operations.move.' + disable + '.' + multi) :
51578             t('operations.move.description.' + multi);
51579     };
51580
51581
51582     operation.id = 'move';
51583     operation.keys = [t('operations.move.key')];
51584     operation.title = t('operations.move.title');
51585     operation.behavior = behaviorOperation(context).which(operation);
51586
51587     return operation;
51588 }
51589
51590 function operationOrthogonalize(selectedIDs, context) {
51591     var entityId = selectedIDs[0],
51592         entity = context.entity(entityId),
51593         extent = entity.extent(context.graph()),
51594         geometry = context.geometry(entityId),
51595         action = actionOrthogonalize(entityId, context.projection);
51596
51597
51598     var operation = function() {
51599         context.perform(action, t('operations.orthogonalize.annotation.' + geometry));
51600     };
51601
51602
51603     operation.available = function() {
51604         return selectedIDs.length === 1 &&
51605             entity.type === 'way' &&
51606             entity.isClosed() &&
51607             lodash.uniq(entity.nodes).length > 2;
51608     };
51609
51610
51611     operation.disabled = function() {
51612         var reason;
51613         if (extent.percentContainedIn(context.extent()) < 0.8) {
51614             reason = 'too_large';
51615         } else if (context.hasHiddenConnections(entityId)) {
51616             reason = 'connected_to_hidden';
51617         }
51618         return action.disabled(context.graph()) || reason;
51619     };
51620
51621
51622     operation.tooltip = function() {
51623         var disable = operation.disabled();
51624         return disable ?
51625             t('operations.orthogonalize.' + disable) :
51626             t('operations.orthogonalize.description.' + geometry);
51627     };
51628
51629
51630     operation.id = 'orthogonalize';
51631     operation.keys = [t('operations.orthogonalize.key')];
51632     operation.title = t('operations.orthogonalize.title');
51633     operation.behavior = behaviorOperation(context).which(operation);
51634
51635     return operation;
51636 }
51637
51638 function operationReflectShort(selectedIDs, context) {
51639     return operationReflect(selectedIDs, context, 'short');
51640 }
51641
51642
51643 function operationReflectLong(selectedIDs, context) {
51644     return operationReflect(selectedIDs, context, 'long');
51645 }
51646
51647
51648 function operationReflect(selectedIDs, context, axis) {
51649     axis = axis || 'long';
51650     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51651         extent = selectedIDs.reduce(function(extent, id) {
51652             return extent.extend(context.entity(id).extent(context.graph()));
51653         }, geoExtent$$1());
51654
51655
51656     var operation = function() {
51657         var action = actionReflect(selectedIDs, context.projection)
51658             .useLongAxis(Boolean(axis === 'long'));
51659         context.perform(action, t('operations.reflect.annotation.' + axis + '.' + multi));
51660     };
51661
51662
51663     operation.available = function() {
51664         return lodash.some(selectedIDs, hasArea);
51665
51666         function hasArea(id) {
51667             var entity = context.entity(id);
51668             return (entity.type === 'way' && entity.isClosed()) ||
51669                 (entity.type ==='relation' && entity.isMultipolygon());
51670         }
51671     };
51672
51673
51674     operation.disabled = function() {
51675         var reason;
51676         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51677             reason = 'too_large';
51678         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51679             reason = 'connected_to_hidden';
51680         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51681             reason = 'incomplete_relation';
51682         }
51683         return reason;
51684
51685         function incompleteRelation(id) {
51686             var entity = context.entity(id);
51687             return entity.type === 'relation' && !entity.isComplete(context.graph());
51688         }
51689     };
51690
51691
51692     operation.tooltip = function() {
51693         var disable = operation.disabled();
51694         return disable ?
51695             t('operations.reflect.' + disable + '.' + multi) :
51696             t('operations.reflect.description.' + axis + '.' + multi);
51697     };
51698
51699
51700     operation.id = 'reflect-' + axis;
51701     operation.keys = [t('operations.reflect.key.' + axis)];
51702     operation.title = t('operations.reflect.title');
51703     operation.behavior = behaviorOperation(context).which(operation);
51704
51705     return operation;
51706 }
51707
51708 function operationReverse(selectedIDs, context) {
51709     var entityId = selectedIDs[0];
51710
51711     var operation = function() {
51712         context.perform(actionReverse(entityId), t('operations.reverse.annotation'));
51713     };
51714
51715
51716     operation.available = function() {
51717         return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
51718     };
51719
51720
51721     operation.disabled = function() {
51722         return false;
51723     };
51724
51725
51726     operation.tooltip = function() {
51727         return t('operations.reverse.description');
51728     };
51729
51730
51731     operation.id = 'reverse';
51732     operation.keys = [t('operations.reverse.key')];
51733     operation.title = t('operations.reverse.title');
51734     operation.behavior = behaviorOperation(context).which(operation);
51735
51736     return operation;
51737 }
51738
51739 function operationRotate(selectedIDs, context) {
51740     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51741         extent = selectedIDs.reduce(function(extent, id) {
51742             return extent.extend(context.entity(id).extent(context.graph()));
51743         }, geoExtent$$1());
51744
51745
51746     var operation = function() {
51747         context.enter(modeRotate$$1(context, selectedIDs));
51748     };
51749
51750
51751     operation.available = function() {
51752         return lodash.some(selectedIDs, hasArea);
51753
51754         function hasArea(id) {
51755             var entity = context.entity(id);
51756             return (entity.type === 'way' && entity.isClosed()) ||
51757                 (entity.type ==='relation' && entity.isMultipolygon());
51758         }
51759     };
51760
51761
51762     operation.disabled = function() {
51763         var reason;
51764         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51765             reason = 'too_large';
51766         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51767             reason = 'connected_to_hidden';
51768         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51769             reason = 'incomplete_relation';
51770         }
51771         return reason;
51772
51773         function incompleteRelation(id) {
51774             var entity = context.entity(id);
51775             return entity.type === 'relation' && !entity.isComplete(context.graph());
51776         }
51777     };
51778
51779
51780     operation.tooltip = function() {
51781         var disable = operation.disabled();
51782         return disable ?
51783             t('operations.rotate.' + disable + '.' + multi) :
51784             t('operations.rotate.description.' + multi);
51785     };
51786
51787
51788     operation.id = 'rotate';
51789     operation.keys = [t('operations.rotate.key')];
51790     operation.title = t('operations.rotate.title');
51791     operation.behavior = behaviorOperation(context).which(operation);
51792
51793     return operation;
51794 }
51795
51796 function operationSplit(selectedIDs, context) {
51797     var vertices = lodash.filter(selectedIDs, function(entityId) {
51798         return context.geometry(entityId) === 'vertex';
51799     });
51800
51801     var entityId = vertices[0],
51802         action = actionSplit(entityId);
51803
51804     if (selectedIDs.length > 1) {
51805         action.limitWays(lodash.without(selectedIDs, entityId));
51806     }
51807
51808
51809     var operation = function() {
51810         var annotation;
51811
51812         var ways = action.ways(context.graph());
51813         if (ways.length === 1) {
51814             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51815         } else {
51816             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51817         }
51818
51819         var difference = context.perform(action, annotation);
51820         context.enter(modeSelect(context, difference.extantIDs()));
51821     };
51822
51823
51824     operation.available = function() {
51825         return vertices.length === 1;
51826     };
51827
51828
51829     operation.disabled = function() {
51830         var reason;
51831         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51832             reason = 'connected_to_hidden';
51833         }
51834         return action.disabled(context.graph()) || reason;
51835     };
51836
51837
51838     operation.tooltip = function() {
51839         var disable = operation.disabled();
51840         if (disable) {
51841             return t('operations.split.' + disable);
51842         }
51843
51844         var ways = action.ways(context.graph());
51845         if (ways.length === 1) {
51846             return t('operations.split.description.' + context.geometry(ways[0].id));
51847         } else {
51848             return t('operations.split.description.multiple');
51849         }
51850     };
51851
51852
51853     operation.id = 'split';
51854     operation.keys = [t('operations.split.key')];
51855     operation.title = t('operations.split.title');
51856     operation.behavior = behaviorOperation(context).which(operation);
51857
51858     return operation;
51859 }
51860
51861 function operationStraighten(selectedIDs, context) {
51862     var entityId = selectedIDs[0],
51863         action = actionStraighten(entityId, context.projection);
51864
51865
51866     function operation() {
51867         context.perform(action, t('operations.straighten.annotation'));
51868     }
51869
51870
51871     operation.available = function() {
51872         var entity = context.entity(entityId);
51873         return selectedIDs.length === 1 &&
51874             entity.type === 'way' &&
51875             !entity.isClosed() &&
51876             lodash.uniq(entity.nodes).length > 2;
51877     };
51878
51879
51880     operation.disabled = function() {
51881         var reason;
51882         if (context.hasHiddenConnections(entityId)) {
51883             reason = 'connected_to_hidden';
51884         }
51885         return action.disabled(context.graph()) || reason;
51886     };
51887
51888
51889     operation.tooltip = function() {
51890         var disable = operation.disabled();
51891         return disable ?
51892             t('operations.straighten.' + disable) :
51893             t('operations.straighten.description');
51894     };
51895
51896
51897     operation.id = 'straighten';
51898     operation.keys = [t('operations.straighten.key')];
51899     operation.title = t('operations.straighten.title');
51900     operation.behavior = behaviorOperation(context).which(operation);
51901
51902     return operation;
51903 }
51904
51905
51906
51907 var Operations = Object.freeze({
51908         operationCircularize: operationCircularize,
51909         operationContinue: operationContinue,
51910         operationDelete: operationDelete,
51911         operationDisconnect: operationDisconnect,
51912         operationMerge: operationMerge,
51913         operationMove: operationMove,
51914         operationOrthogonalize: operationOrthogonalize,
51915         operationReflectShort: operationReflectShort,
51916         operationReflectLong: operationReflectLong,
51917         operationReverse: operationReverse,
51918         operationRotate: operationRotate,
51919         operationSplit: operationSplit,
51920         operationStraighten: operationStraighten
51921 });
51922
51923 function modeMove$$1(context, entityIDs, baseGraph) {
51924     var mode = {
51925         id: 'move',
51926         button: 'browse'
51927     };
51928
51929     var keybinding = d3keybinding('move'),
51930         behaviors = [
51931             behaviorEdit(context),
51932             operationCircularize(entityIDs, context).behavior,
51933             operationDelete(entityIDs, context).behavior,
51934             operationOrthogonalize(entityIDs, context).behavior,
51935             operationReflectLong(entityIDs, context).behavior,
51936             operationReflectShort(entityIDs, context).behavior,
51937             operationRotate(entityIDs, context).behavior
51938         ],
51939         annotation = entityIDs.length === 1 ?
51940             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
51941             t('operations.move.annotation.multiple'),
51942         prevGraph,
51943         cache,
51944         origin,
51945         nudgeInterval;
51946
51947
51948     function vecSub(a, b) {
51949         return [a[0] - b[0], a[1] - b[1]];
51950     }
51951
51952
51953     function edge(point, size) {
51954         var pad = [30, 100, 30, 100],
51955             x = 0,
51956             y = 0;
51957
51958         if (point[0] > size[0] - pad[0])
51959             x = -10;
51960         if (point[0] < pad[2])
51961             x = 10;
51962         if (point[1] > size[1] - pad[1])
51963             y = -10;
51964         if (point[1] < pad[3])
51965             y = 10;
51966
51967         if (x || y) return [x, y];
51968         else return null;
51969     }
51970
51971
51972     function doMove(nudge) {
51973         nudge = nudge || [0, 0];
51974
51975         var fn;
51976         if (prevGraph !== context.graph()) {
51977             cache = {};
51978             origin = context.map().mouseCoordinates();
51979             fn = context.perform;
51980         } else {
51981             fn = context.overwrite;
51982         }
51983
51984         var currMouse = context.mouse(),
51985             origMouse = context.projection(origin),
51986             delta = vecSub(vecSub(currMouse, origMouse), nudge);
51987
51988         fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
51989         prevGraph = context.graph();
51990     }
51991
51992
51993     function startNudge(nudge) {
51994         if (nudgeInterval) window.clearInterval(nudgeInterval);
51995         nudgeInterval = window.setInterval(function() {
51996             context.pan(nudge);
51997             doMove(nudge);
51998         }, 50);
51999     }
52000
52001
52002     function stopNudge() {
52003         if (nudgeInterval) window.clearInterval(nudgeInterval);
52004         nudgeInterval = null;
52005     }
52006
52007
52008     function move() {
52009         doMove();
52010         var nudge = edge(context.mouse(), context.map().dimensions());
52011         if (nudge) startNudge(nudge);
52012         else stopNudge();
52013     }
52014
52015
52016     function finish() {
52017         event.stopPropagation();
52018         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52019         stopNudge();
52020     }
52021
52022
52023     function cancel() {
52024         if (baseGraph) {
52025             while (context.graph() !== baseGraph) context.pop();
52026             context.enter(modeBrowse(context));
52027         } else {
52028             context.pop();
52029             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52030         }
52031         stopNudge();
52032     }
52033
52034
52035     function undone() {
52036         context.enter(modeBrowse(context));
52037     }
52038
52039
52040     mode.enter = function() {
52041         origin = context.map().mouseCoordinates();
52042         prevGraph = null;
52043         cache = {};
52044
52045         behaviors.forEach(function(behavior) {
52046             context.install(behavior);
52047         });
52048
52049         context.surface()
52050             .on('mousemove.move', move)
52051             .on('click.move', finish);
52052
52053         context.history()
52054             .on('undone.move', undone);
52055
52056         keybinding
52057             .on('⎋', cancel)
52058             .on('↩', finish);
52059
52060         select(document)
52061             .call(keybinding);
52062     };
52063
52064
52065     mode.exit = function() {
52066         stopNudge();
52067
52068         behaviors.forEach(function(behavior) {
52069             context.uninstall(behavior);
52070         });
52071
52072         context.surface()
52073             .on('mousemove.move', null)
52074             .on('click.move', null);
52075
52076         context.history()
52077             .on('undone.move', null);
52078
52079         keybinding.off();
52080     };
52081
52082
52083     return mode;
52084 }
52085
52086 function modeRotate$$1(context, entityIDs) {
52087     var mode = {
52088         id: 'rotate',
52089         button: 'browse'
52090     };
52091
52092     var keybinding = d3keybinding('rotate'),
52093         behaviors = [
52094             behaviorEdit(context),
52095             operationCircularize(entityIDs, context).behavior,
52096             operationDelete(entityIDs, context).behavior,
52097             operationMove(entityIDs, context).behavior,
52098             operationOrthogonalize(entityIDs, context).behavior,
52099             operationReflectLong(entityIDs, context).behavior,
52100             operationReflectShort(entityIDs, context).behavior
52101         ],
52102         annotation = entityIDs.length === 1 ?
52103             t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
52104             t('operations.rotate.annotation.multiple'),
52105         prevGraph,
52106         prevAngle,
52107         prevTransform,
52108         pivot;
52109
52110
52111     function doRotate() {
52112         var fn;
52113         if (context.graph() !== prevGraph) {
52114             fn = context.perform;
52115         } else {
52116             fn = context.replace;
52117         }
52118
52119         // projection changed, recalculate pivot
52120         var projection = context.projection;
52121         var currTransform = projection.transform();
52122         if (!prevTransform ||
52123             currTransform.k !== prevTransform.k ||
52124             currTransform.x !== prevTransform.x ||
52125             currTransform.y !== prevTransform.y) {
52126
52127             var nodes = utilGetAllNodes(entityIDs, context.graph()),
52128                 points = nodes.map(function(n) { return projection(n.loc); });
52129
52130             pivot = d3polygonCentroid(d3polygonHull(points));
52131             prevAngle = undefined;
52132         }
52133
52134
52135         var currMouse = context.mouse(),
52136             currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
52137
52138         if (typeof prevAngle === 'undefined') prevAngle = currAngle;
52139         var delta = currAngle - prevAngle;
52140
52141         fn(actionRotate(entityIDs, pivot, delta, projection), annotation);
52142
52143         prevTransform = currTransform;
52144         prevAngle = currAngle;
52145         prevGraph = context.graph();
52146     }
52147
52148
52149     function finish() {
52150         event.stopPropagation();
52151         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52152     }
52153
52154
52155     function cancel() {
52156         context.pop();
52157         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52158     }
52159
52160
52161     function undone() {
52162         context.enter(modeBrowse(context));
52163     }
52164
52165
52166     mode.enter = function() {
52167         behaviors.forEach(function(behavior) {
52168             context.install(behavior);
52169         });
52170
52171         context.surface()
52172             .on('mousemove.rotate', doRotate)
52173             .on('click.rotate', finish);
52174
52175         context.history()
52176             .on('undone.rotate', undone);
52177
52178         keybinding
52179             .on('⎋', cancel)
52180             .on('↩', finish);
52181
52182         select(document)
52183             .call(keybinding);
52184     };
52185
52186
52187     mode.exit = function() {
52188         behaviors.forEach(function(behavior) {
52189             context.uninstall(behavior);
52190         });
52191
52192         context.surface()
52193             .on('mousemove.rotate', null)
52194             .on('click.rotate', null);
52195
52196         context.history()
52197             .on('undone.rotate', null);
52198
52199         keybinding.off();
52200     };
52201
52202
52203     return mode;
52204 }
52205
52206 function modeSave$$1(context) {
52207     var mode = {
52208         id: 'save'
52209     };
52210
52211     var ui = uiCommit(context)
52212             .on('cancel', cancel)
52213             .on('save', save);
52214
52215
52216     function cancel() {
52217         context.enter(modeBrowse(context));
52218     }
52219
52220
52221     function save(e, tryAgain) {
52222         function withChildNodes(ids, graph) {
52223             return lodash.uniq(lodash.reduce(ids, function(result, id) {
52224                 var e = graph.entity(id);
52225                 if (e.type === 'way') {
52226                     try {
52227                         var cn = graph.childNodes(e);
52228                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
52229                     } catch (err) {
52230                         /* eslint-disable no-console */
52231                         if (typeof console !== 'undefined') console.error(err);
52232                         /* eslint-enable no-console */
52233                     }
52234                 }
52235                 return result;
52236             }, lodash.clone(ids)));
52237         }
52238
52239         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
52240             history = context.history(),
52241             origChanges = history.changes(actionDiscardTags(history.difference())),
52242             localGraph = context.graph(),
52243             remoteGraph = coreGraph$$1(history.base(), true),
52244             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
52245             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
52246             toLoad = withChildNodes(toCheck, localGraph),
52247             conflicts = [],
52248             errors = [];
52249
52250         if (!tryAgain) history.perform(actionNoop());  // checkpoint
52251         context.container().call(loading);
52252
52253         if (toCheck.length) {
52254             context.connection().loadMultiple(toLoad, loaded);
52255         } else {
52256             finalize();
52257         }
52258
52259
52260         // Reload modified entities into an alternate graph and check for conflicts..
52261         function loaded(err, result) {
52262             if (errors.length) return;
52263
52264             if (err) {
52265                 errors.push({
52266                     msg: err.responseText,
52267                     details: [ t('save.status_code', { code: err.status }) ]
52268                 });
52269                 showErrors();
52270
52271             } else {
52272                 var loadMore = [];
52273                 lodash.each(result.data, function(entity) {
52274                     remoteGraph.replace(entity);
52275                     toLoad = lodash.without(toLoad, entity.id);
52276
52277                     // Because loadMultiple doesn't download /full like loadEntity,
52278                     // need to also load children that aren't already being checked..
52279                     if (!entity.visible) return;
52280                     if (entity.type === 'way') {
52281                         loadMore.push.apply(loadMore,
52282                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
52283                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
52284                         loadMore.push.apply(loadMore,
52285                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
52286                     }
52287                 });
52288
52289                 if (loadMore.length) {
52290                     toLoad.push.apply(toLoad, loadMore);
52291                     context.connection().loadMultiple(loadMore, loaded);
52292                 }
52293
52294                 if (!toLoad.length) {
52295                     checkConflicts();
52296                 }
52297             }
52298         }
52299
52300
52301         function checkConflicts() {
52302             function choice(id, text$$1, action) {
52303                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
52304             }
52305             function formatUser(d) {
52306                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
52307             }
52308             function entityName(entity) {
52309                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
52310             }
52311
52312             function compareVersions(local$$1, remote) {
52313                 if (local$$1.version !== remote.version) return false;
52314
52315                 if (local$$1.type === 'way') {
52316                     var children = lodash.union(local$$1.nodes, remote.nodes);
52317
52318                     for (var i = 0; i < children.length; i++) {
52319                         var a = localGraph.hasEntity(children[i]),
52320                             b = remoteGraph.hasEntity(children[i]);
52321
52322                         if (a && b && a.version !== b.version) return false;
52323                     }
52324                 }
52325
52326                 return true;
52327             }
52328
52329             lodash.each(toCheck, function(id) {
52330                 var local$$1 = localGraph.entity(id),
52331                     remote = remoteGraph.entity(id);
52332
52333                 if (compareVersions(local$$1, remote)) return;
52334
52335                 var action = actionMergeRemoteChanges,
52336                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
52337
52338                 history.replace(merge$$1);
52339
52340                 var mergeConflicts = merge$$1.conflicts();
52341                 if (!mergeConflicts.length) return;  // merged safely
52342
52343                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
52344                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
52345                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
52346                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
52347
52348                 conflicts.push({
52349                     id: id,
52350                     name: entityName(local$$1),
52351                     details: mergeConflicts,
52352                     chosen: 1,
52353                     choices: [
52354                         choice(id, keepMine, forceLocal),
52355                         choice(id, keepTheirs, forceRemote)
52356                     ]
52357                 });
52358             });
52359
52360             finalize();
52361         }
52362
52363
52364         function finalize() {
52365             if (conflicts.length) {
52366                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
52367                 showConflicts();
52368             } else if (errors.length) {
52369                 showErrors();
52370             } else {
52371                 var changes = history.changes(actionDiscardTags(history.difference()));
52372                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
52373                     context.connection().putChangeset(
52374                         changes,
52375                         context.version,
52376                         e.comment,
52377                         history.imageryUsed(),
52378                         function(err, changeset_id) {
52379                             if (err) {
52380                                 errors.push({
52381                                     msg: err.responseText,
52382                                     details: [ t('save.status_code', { code: err.status }) ]
52383                                 });
52384                                 showErrors();
52385                             } else {
52386                                 history.clearSaved();
52387                                 success(e, changeset_id);
52388                                 // Add delay to allow for postgres replication #1646 #2678
52389                                 window.setTimeout(function() {
52390                                     loading.close();
52391                                     context.flush();
52392                                 }, 2500);
52393                             }
52394                         });
52395                 } else {        // changes were insignificant or reverted by user
52396                     loading.close();
52397                     context.flush();
52398                     cancel();
52399                 }
52400             }
52401         }
52402
52403
52404         function showConflicts() {
52405             var selection$$1 = context.container()
52406                 .select('#sidebar')
52407                 .append('div')
52408                 .attr('class','sidebar-component');
52409
52410             loading.close();
52411
52412             selection$$1.call(uiConflicts(context)
52413                 .list(conflicts)
52414                 .on('download', function() {
52415                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
52416                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
52417                     win.focus();
52418                 })
52419                 .on('cancel', function() {
52420                     history.pop();
52421                     selection$$1.remove();
52422                 })
52423                 .on('save', function() {
52424                     for (var i = 0; i < conflicts.length; i++) {
52425                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
52426                             var entity = context.hasEntity(conflicts[i].id);
52427                             if (entity && entity.type === 'way') {
52428                                 var children = lodash.uniq(entity.nodes);
52429                                 for (var j = 0; j < children.length; j++) {
52430                                     history.replace(actionRevert(children[j]));
52431                                 }
52432                             }
52433                             history.replace(actionRevert(conflicts[i].id));
52434                         }
52435                     }
52436
52437                     selection$$1.remove();
52438                     save(e, true);
52439                 })
52440             );
52441         }
52442
52443
52444         function showErrors() {
52445             var selection$$1 = uiConfirm(context.container());
52446
52447             history.pop();
52448             loading.close();
52449
52450             selection$$1
52451                 .select('.modal-section.header')
52452                 .append('h3')
52453                 .text(t('save.error'));
52454
52455             addErrors(selection$$1, errors);
52456             selection$$1.okButton();
52457         }
52458
52459
52460         function addErrors(selection$$1, data) {
52461             var message = selection$$1
52462                 .select('.modal-section.message-text');
52463
52464             var items = message
52465                 .selectAll('.error-container')
52466                 .data(data);
52467
52468             var enter = items.enter()
52469                 .append('div')
52470                 .attr('class', 'error-container');
52471
52472             enter
52473                 .append('a')
52474                 .attr('class', 'error-description')
52475                 .attr('href', '#')
52476                 .classed('hide-toggle', true)
52477                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
52478                 .on('click', function() {
52479                     var error = select(this),
52480                         detail = select(this.nextElementSibling),
52481                         exp = error.classed('expanded');
52482
52483                     detail.style('display', exp ? 'none' : 'block');
52484                     error.classed('expanded', !exp);
52485
52486                     event.preventDefault();
52487                 });
52488
52489             var details = enter
52490                 .append('div')
52491                 .attr('class', 'error-detail-container')
52492                 .style('display', 'none');
52493
52494             details
52495                 .append('ul')
52496                 .attr('class', 'error-detail-list')
52497                 .selectAll('li')
52498                 .data(function(d) { return d.details || []; })
52499                 .enter()
52500                 .append('li')
52501                 .attr('class', 'error-detail-item')
52502                 .text(function(d) { return d; });
52503
52504             items.exit()
52505                 .remove();
52506         }
52507
52508     }
52509
52510
52511     function success(e, changeset_id) {
52512         context.enter(modeBrowse(context)
52513             .sidebar(uiSuccess(context)
52514                 .changeset({
52515                     id: changeset_id,
52516                     comment: e.comment
52517                 })
52518                 .on('cancel', function() {
52519                     context.ui().sidebar.hide();
52520                 })
52521             )
52522         );
52523     }
52524
52525
52526     mode.enter = function() {
52527         function done() {
52528             context.ui().sidebar.show(ui);
52529         }
52530
52531         context.container().selectAll('#content')
52532             .attr('class', 'inactive');
52533
52534         if (context.connection().authenticated()) {
52535             done();
52536         } else {
52537             context.connection().authenticate(function(err) {
52538                 if (err) {
52539                     cancel();
52540                 } else {
52541                     done();
52542                 }
52543             });
52544         }
52545     };
52546
52547
52548     mode.exit = function() {
52549         context.container().selectAll('#content')
52550             .attr('class', 'active');
52551
52552         context.ui().sidebar.hide();
52553     };
52554
52555     return mode;
52556 }
52557
52558 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
52559 // For example, ⌘Z -> Ctrl+Z
52560 function uiCmd(code) {
52561     var detected = utilDetect();
52562
52563     if (detected.os === 'mac') {
52564         return code;
52565     }
52566
52567     if (detected.os === 'win') {
52568         if (code === '⌘⇧Z') return 'Ctrl+Y';
52569     }
52570
52571     var result = '',
52572         replacements = {
52573             '⌘': 'Ctrl',
52574             '⇧': 'Shift',
52575             '⌥': 'Alt',
52576             '⌫': 'Backspace',
52577             '⌦': 'Delete'
52578         };
52579
52580     for (var i = 0; i < code.length; i++) {
52581         if (code[i] in replacements) {
52582             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
52583         } else {
52584             result += code[i];
52585         }
52586     }
52587
52588     return result;
52589 }
52590
52591 var relatedParent;
52592
52593
52594 function modeSelect(context, selectedIDs) {
52595     var mode = {
52596         id: 'select',
52597         button: 'browse'
52598     };
52599
52600     var keybinding = d3keybinding('select'),
52601         timeout$$1 = null,
52602         behaviors = [
52603             behaviorCopy(context),
52604             behaviorPaste(context),
52605             behaviorBreathe(context),
52606             behaviorHover(context),
52607             behaviorSelect(context),
52608             behaviorLasso(context),
52609             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
52610         ],
52611         inspector,
52612         radialMenu,
52613         newFeature = false,
52614         suppressMenu = false,
52615         follow = false;
52616
52617
52618     var wrap = context.container()
52619         .select('.inspector-wrap');
52620
52621
52622     function singular() {
52623         if (selectedIDs.length === 1) {
52624             return context.hasEntity(selectedIDs[0]);
52625         }
52626     }
52627
52628
52629     function checkSelectedIDs() {
52630         var ids = [];
52631         if (Array.isArray(selectedIDs)) {
52632             ids = selectedIDs.filter(function(id) {
52633                 return context.hasEntity(id);
52634             });
52635         }
52636
52637         if (ids.length) {
52638             selectedIDs = ids;
52639         } else {
52640             context.enter(modeBrowse(context));
52641         }
52642         return !!ids.length;
52643     }
52644
52645
52646     // find the common parent ways for nextVertex, previousVertex
52647     function commonParents() {
52648         var graph = context.graph(),
52649             commonParents = [];
52650
52651         for (var i = 0; i < selectedIDs.length; i++) {
52652             var entity = context.hasEntity(selectedIDs[i]);
52653             if (!entity || entity.geometry(graph) !== 'vertex') {
52654                 return [];  // selection includes some not vertexes
52655             }
52656
52657             var currParents = lodash.map(graph.parentWays(entity), 'id');
52658             if (!commonParents.length) {
52659                 commonParents = currParents;
52660                 continue;
52661             }
52662
52663             commonParents = lodash.intersection(commonParents, currParents);
52664             if (!commonParents.length) {
52665                 return [];
52666             }
52667         }
52668
52669         return commonParents;
52670     }
52671
52672
52673     function singularParent() {
52674         var parents = commonParents();
52675         if (!parents || parents.length === 0) {
52676             relatedParent = null;
52677             return null;
52678         }
52679
52680         // relatedParent is used when we visit a vertex with multiple
52681         // parents, and we want to remember which parent line we started on.
52682
52683         if (parents.length === 1) {
52684             relatedParent = parents[0];  // remember this parent for later
52685             return relatedParent;
52686         }
52687
52688         if (parents.indexOf(relatedParent) !== -1) {
52689             return relatedParent;   // prefer the previously seen parent
52690         }
52691
52692         return parents[0];
52693     }
52694
52695
52696     function closeMenu() {
52697         if (radialMenu) {
52698             context.surface().call(radialMenu.close);
52699         }
52700     }
52701
52702
52703     function positionMenu() {
52704         if (suppressMenu || !radialMenu) { return; }
52705
52706         var entity = singular();
52707         if (entity && context.geometry(entity.id) === 'relation') {
52708             suppressMenu = true;
52709         } else if (entity && entity.type === 'node') {
52710             radialMenu.center(context.projection(entity.loc));
52711         } else {
52712             var point = context.mouse(),
52713                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
52714             if (geoPointInPolygon(point, viewport)) {
52715                 radialMenu.center(point);
52716             } else {
52717                 suppressMenu = true;
52718             }
52719         }
52720     }
52721
52722
52723     function showMenu() {
52724         closeMenu();
52725         if (!suppressMenu && radialMenu) {
52726             context.surface().call(radialMenu);
52727         }
52728     }
52729
52730
52731     function toggleMenu() {
52732         if (select('.radial-menu').empty()) {
52733             showMenu();
52734         } else {
52735             closeMenu();
52736         }
52737     }
52738
52739
52740     mode.selectedIDs = function() {
52741         return selectedIDs;
52742     };
52743
52744
52745     mode.reselect = function() {
52746         if (!checkSelectedIDs()) return;
52747
52748         var surfaceNode = context.surface().node();
52749         if (surfaceNode.focus) {   // FF doesn't support it
52750             surfaceNode.focus();
52751         }
52752
52753         positionMenu();
52754         showMenu();
52755     };
52756
52757
52758     mode.newFeature = function(_) {
52759         if (!arguments.length) return newFeature;
52760         newFeature = _;
52761         return mode;
52762     };
52763
52764
52765     mode.suppressMenu = function(_) {
52766         if (!arguments.length) return suppressMenu;
52767         suppressMenu = _;
52768         return mode;
52769     };
52770
52771
52772     mode.follow = function(_) {
52773         if (!arguments.length) return follow;
52774         follow = _;
52775         return mode;
52776     };
52777
52778
52779     mode.enter = function() {
52780
52781         function update() {
52782             closeMenu();
52783             checkSelectedIDs();
52784         }
52785
52786
52787         function dblclick() {
52788             var target = select(event.target),
52789                 datum = target.datum();
52790
52791             if (datum instanceof osmWay && !target.classed('fill')) {
52792                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
52793                     prev = datum.nodes[choice.index - 1],
52794                     next = datum.nodes[choice.index];
52795
52796                 context.perform(
52797                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
52798                     t('operations.add.annotation.vertex')
52799                 );
52800
52801                 event.preventDefault();
52802                 event.stopPropagation();
52803             } else if (datum.type === 'midpoint') {
52804                 context.perform(
52805                     actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
52806                     t('operations.add.annotation.vertex'));
52807
52808                 event.preventDefault();
52809                 event.stopPropagation();
52810             }
52811         }
52812
52813
52814         function selectElements(drawn) {
52815             if (!checkSelectedIDs()) return;
52816
52817             var surface = context.surface(),
52818                 entity = singular();
52819
52820             if (entity && context.geometry(entity.id) === 'relation') {
52821                 suppressMenu = true;
52822                 return;
52823             }
52824
52825             surface.selectAll('.related')
52826                 .classed('related', false);
52827
52828             singularParent();
52829             if (relatedParent) {
52830                 surface.selectAll(utilEntitySelector([relatedParent]))
52831                     .classed('related', true);
52832             }
52833
52834             var selection$$1 = context.surface()
52835                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
52836
52837             if (selection$$1.empty()) {
52838                 // Return to browse mode if selected DOM elements have
52839                 // disappeared because the user moved them out of view..
52840                 var source = event && event.type === 'zoom' && event.sourceEvent;
52841                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
52842                     context.enter(modeBrowse(context));
52843                 }
52844             } else {
52845                 selection$$1
52846                     .classed('selected', true);
52847             }
52848         }
52849
52850
52851         function esc() {
52852             if (!context.inIntro()) {
52853                 context.enter(modeBrowse(context));
52854             }
52855         }
52856
52857
52858         function firstVertex() {
52859             event.preventDefault();
52860             var parent = singularParent();
52861             if (parent) {
52862                 var way = context.entity(parent);
52863                 context.enter(
52864                     modeSelect(context, [way.first()]).follow(true).suppressMenu(true)
52865                 );
52866             }
52867         }
52868
52869
52870         function lastVertex() {
52871             event.preventDefault();
52872             var parent = singularParent();
52873             if (parent) {
52874                 var way = context.entity(parent);
52875                 context.enter(
52876                     modeSelect(context, [way.last()]).follow(true).suppressMenu(true)
52877                 );
52878             }
52879         }
52880
52881
52882         function previousVertex() {
52883             event.preventDefault();
52884             var parent = singularParent();
52885             if (!parent) return;
52886
52887             var way = context.entity(parent),
52888                 length = way.nodes.length,
52889                 curr = way.nodes.indexOf(selectedIDs[0]),
52890                 index = -1;
52891
52892             if (curr > 0) {
52893                 index = curr - 1;
52894             } else if (way.isClosed()) {
52895                 index = length - 2;
52896             }
52897
52898             if (index !== -1) {
52899                 context.enter(
52900                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52901                 );
52902             }
52903         }
52904
52905
52906         function nextVertex() {
52907             event.preventDefault();
52908             var parent = singularParent();
52909             if (!parent) return;
52910
52911             var way = context.entity(parent),
52912                 length = way.nodes.length,
52913                 curr = way.nodes.indexOf(selectedIDs[0]),
52914                 index = -1;
52915
52916             if (curr < length - 1) {
52917                 index = curr + 1;
52918             } else if (way.isClosed()) {
52919                 index = 0;
52920             }
52921
52922             if (index !== -1) {
52923                 context.enter(
52924                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52925                 );
52926             }
52927         }
52928
52929
52930         function nextParent() {
52931             event.preventDefault();
52932             var parents = lodash.uniq(commonParents());
52933             if (!parents || parents.length < 2) return;
52934
52935             var index = parents.indexOf(relatedParent);
52936             if (index < 0 || index > parents.length - 2) {
52937                 relatedParent = parents[0];
52938             } else {
52939                 relatedParent = parents[index + 1];
52940             }
52941
52942             var surface = context.surface();
52943             surface.selectAll('.related')
52944                 .classed('related', false);
52945
52946             if (relatedParent) {
52947                 surface.selectAll(utilEntitySelector([relatedParent]))
52948                     .classed('related', true);
52949             }
52950         }
52951
52952
52953         if (!checkSelectedIDs()) return;
52954
52955         var operations = lodash.without(values(Operations), operationDelete)
52956                 .map(function(o) { return o(selectedIDs, context); })
52957                 .filter(function(o) { return o.available(); });
52958
52959         operations.unshift(operationDelete(selectedIDs, context));
52960
52961         operations.forEach(function(operation) {
52962             if (operation.behavior) {
52963                 behaviors.push(operation.behavior);
52964             }
52965         });
52966
52967         behaviors.forEach(function(behavior) {
52968             context.install(behavior);
52969         });
52970
52971         keybinding
52972             .on(['[','pgup'], previousVertex)
52973             .on([']', 'pgdown'], nextVertex)
52974             .on([uiCmd('⌘['), 'home'], firstVertex)
52975             .on([uiCmd('⌘]'), 'end'], lastVertex)
52976             .on(['\\', 'pause'], nextParent)
52977             .on('⎋', esc, true)
52978             .on('space', toggleMenu);
52979
52980         select(document)
52981             .call(keybinding);
52982
52983         radialMenu = uiRadialMenu(context, operations);
52984
52985         context.ui().sidebar
52986             .select(singular() ? singular().id : null, newFeature);
52987
52988         context.history()
52989             .on('undone.select', update)
52990             .on('redone.select', update);
52991
52992         context.map()
52993             .on('move.select', closeMenu)
52994             .on('drawn.select', selectElements);
52995
52996         selectElements();
52997
52998         var show = event && !suppressMenu;
52999
53000         if (show) {
53001             positionMenu();
53002         }
53003
53004         if (follow) {
53005             var extent$$1 = geoExtent$$1(),
53006                 graph = context.graph();
53007             selectedIDs.forEach(function(id) {
53008                 var entity = context.entity(id);
53009                 extent$$1._extend(entity.extent(graph));
53010             });
53011
53012             var loc = extent$$1.center();
53013             context.map().centerEase(loc);
53014         }
53015
53016         timeout$$1 = window.setTimeout(function() {
53017             if (show) {
53018                 showMenu();
53019             }
53020
53021             context.surface()
53022                 .on('dblclick.select', dblclick);
53023         }, 200);
53024
53025         if (selectedIDs.length > 1) {
53026             var entities = uiSelectionList(context, selectedIDs);
53027             context.ui().sidebar.show(entities);
53028         }
53029     };
53030
53031
53032     mode.exit = function() {
53033         if (timeout$$1) window.clearTimeout(timeout$$1);
53034
53035         if (inspector) wrap.call(inspector.close);
53036
53037         behaviors.forEach(function(behavior) {
53038             context.uninstall(behavior);
53039         });
53040
53041         keybinding.off();
53042         closeMenu();
53043         radialMenu = undefined;
53044
53045         context.history()
53046             .on('undone.select', null)
53047             .on('redone.select', null);
53048
53049         var surface = context.surface();
53050
53051         surface
53052             .on('dblclick.select', null);
53053
53054         surface
53055             .selectAll('.selected')
53056             .classed('selected', false);
53057
53058         surface
53059             .selectAll('.related')
53060             .classed('related', false);
53061
53062         context.map().on('drawn.select', null);
53063         context.ui().sidebar.hide();
53064     };
53065
53066
53067     return mode;
53068 }
53069
53070 function uiAccount(context) {
53071     var connection = context.connection();
53072
53073
53074     function update(selection$$1) {
53075         if (!connection.authenticated()) {
53076             selection$$1.selectAll('#userLink, #logoutLink')
53077                 .classed('hide', true);
53078             return;
53079         }
53080
53081         connection.userDetails(function(err, details) {
53082             var userLink = selection$$1.select('#userLink'),
53083                 logoutLink = selection$$1.select('#logoutLink');
53084
53085             userLink.html('');
53086             logoutLink.html('');
53087
53088             if (err) return;
53089
53090             selection$$1.selectAll('#userLink, #logoutLink')
53091                 .classed('hide', false);
53092
53093             // Link
53094             userLink.append('a')
53095                 .attr('href', connection.userURL(details.display_name))
53096                 .attr('target', '_blank');
53097
53098             // Add thumbnail or dont
53099             if (details.image_url) {
53100                 userLink.append('img')
53101                     .attr('class', 'icon pre-text user-icon')
53102                     .attr('src', details.image_url);
53103             } else {
53104                 userLink
53105                     .call(svgIcon('#icon-avatar', 'pre-text light'));
53106             }
53107
53108             // Add user name
53109             userLink.append('span')
53110                 .attr('class', 'label')
53111                 .text(details.display_name);
53112
53113             logoutLink.append('a')
53114                 .attr('class', 'logout')
53115                 .attr('href', '#')
53116                 .text(t('logout'))
53117                 .on('click.logout', function() {
53118                     event.preventDefault();
53119                     connection.logout();
53120                 });
53121         });
53122     }
53123
53124
53125     return function(selection$$1) {
53126         selection$$1.append('li')
53127             .attr('id', 'logoutLink')
53128             .classed('hide', true);
53129
53130         selection$$1.append('li')
53131             .attr('id', 'userLink')
53132             .classed('hide', true);
53133
53134         connection
53135             .on('change.account', function() { update(selection$$1); });
53136
53137         update(selection$$1);
53138     };
53139 }
53140
53141 function uiAttribution(context) {
53142     var selection$$1;
53143
53144
53145     function attribution(data, klass) {
53146         var div = selection$$1.selectAll('.' + klass)
53147             .data([0]);
53148
53149         div = div.enter()
53150             .append('div')
53151             .attr('class', klass)
53152             .merge(div);
53153
53154
53155         var background = div.selectAll('.attribution')
53156             .data(data, function(d) { return d.name(); });
53157
53158         background.exit()
53159             .remove();
53160
53161         background = background.enter()
53162             .append('span')
53163             .attr('class', 'attribution')
53164             .each(function(d) {
53165                 if (d.terms_html) {
53166                     select(this)
53167                         .html(d.terms_html);
53168                     return;
53169                 }
53170
53171                 var source = d.terms_text || d.id || d.name();
53172
53173                 if (d.logo) {
53174                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
53175                 }
53176
53177                 if (d.terms_url) {
53178                     select(this)
53179                         .append('a')
53180                         .attr('href', d.terms_url)
53181                         .attr('target', '_blank')
53182                         .html(source);
53183                 } else {
53184                     select(this)
53185                         .text(source);
53186                 }
53187             })
53188             .merge(background);
53189
53190
53191         var copyright = background.selectAll('.copyright-notice')
53192             .data(function(d) {
53193                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
53194                 return notice ? [notice] : [];
53195             });
53196
53197         copyright.exit()
53198             .remove();
53199
53200         copyright = copyright.enter()
53201             .append('span')
53202             .attr('class', 'copyright-notice')
53203             .merge(copyright);
53204
53205         copyright
53206             .text(String);
53207     }
53208
53209
53210     function update() {
53211         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
53212         attribution(context.background().overlayLayerSources().filter(function (s) {
53213             return s.validZoom(context.map().zoom());
53214         }), 'overlay-layer-attribution');
53215     }
53216
53217
53218     return function(select$$1) {
53219         selection$$1 = select$$1;
53220
53221         context.background()
53222             .on('change.attribution', update);
53223
53224         context.map()
53225             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
53226
53227         update();
53228     };
53229 }
53230
53231 function rendererBackgroundSource(data) {
53232     var source = lodash.clone(data),
53233         offset = [0, 0],
53234         name = source.name,
53235         best = !!source.best;
53236
53237     source.scaleExtent = data.scaleExtent || [0, 20];
53238     source.overzoom = data.overzoom !== false;
53239
53240
53241     source.offset = function(_) {
53242         if (!arguments.length) return offset;
53243         offset = _;
53244         return source;
53245     };
53246
53247
53248     source.nudge = function(_, zoomlevel) {
53249         offset[0] += _[0] / Math.pow(2, zoomlevel);
53250         offset[1] += _[1] / Math.pow(2, zoomlevel);
53251         return source;
53252     };
53253
53254
53255     source.name = function() {
53256         return name;
53257     };
53258
53259
53260     source.best = function() {
53261         return best;
53262     };
53263
53264
53265     source.area = function() {
53266         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
53267         var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
53268         return isNaN(area$$1) ? 0 : area$$1;
53269     };
53270
53271
53272     source.imageryUsed = function() {
53273         return name || source.id;
53274     };
53275
53276
53277     source.url = function(coord) {
53278         return data.template
53279             .replace('{x}', coord[0])
53280             .replace('{y}', coord[1])
53281             // TMS-flipped y coordinate
53282             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
53283             .replace(/\{z(oom)?\}/, coord[2])
53284             .replace(/\{switch:([^}]+)\}/, function(s, r) {
53285                 var subdomains = r.split(',');
53286                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
53287             })
53288             .replace('{u}', function() {
53289                 var u = '';
53290                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
53291                     var b = 0;
53292                     var mask = 1 << (zoom$$1 - 1);
53293                     if ((coord[0] & mask) !== 0) b++;
53294                     if ((coord[1] & mask) !== 0) b += 2;
53295                     u += b.toString();
53296                 }
53297                 return u;
53298             });
53299     };
53300
53301
53302     source.intersects = function(extent$$1) {
53303         extent$$1 = extent$$1.polygon();
53304         return !data.polygon || data.polygon.some(function(polygon) {
53305             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
53306         });
53307     };
53308
53309
53310     source.validZoom = function(z) {
53311         return source.scaleExtent[0] <= z &&
53312             (source.overzoom || source.scaleExtent[1] > z);
53313     };
53314
53315
53316     source.isLocatorOverlay = function() {
53317         return source.id === 'mapbox_locator_overlay';
53318     };
53319
53320
53321     source.copyrightNotices = function() {};
53322
53323
53324     return source;
53325 }
53326
53327
53328 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
53329     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
53330     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
53331
53332     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
53333
53334     var bing = rendererBackgroundSource(data),
53335         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
53336         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
53337             key + '&jsonp={callback}',
53338         providers = [];
53339
53340     jsonpRequest(url, function(json$$1) {
53341         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
53342             return {
53343                 attribution: provider.attribution,
53344                 areas: provider.coverageAreas.map(function(area$$1) {
53345                     return {
53346                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
53347                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
53348                     };
53349                 })
53350             };
53351         });
53352         dispatch$$1.call('change');
53353     });
53354
53355     bing.copyrightNotices = function(zoom$$1, extent$$1) {
53356         zoom$$1 = Math.min(zoom$$1, 21);
53357         return providers.filter(function(provider) {
53358             return lodash.some(provider.areas, function(area$$1) {
53359                 return extent$$1.intersects(area$$1.extent) &&
53360                     area$$1.zoom[0] <= zoom$$1 &&
53361                     area$$1.zoom[1] >= zoom$$1;
53362             });
53363         }).map(function(provider) {
53364             return provider.attribution;
53365         }).join(', ');
53366     };
53367
53368     bing.logo = 'bing_maps.png';
53369     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
53370
53371     return bing;
53372 };
53373
53374
53375 rendererBackgroundSource.None = function() {
53376     var source = rendererBackgroundSource({ id: 'none', template: '' });
53377
53378     source.name = function() {
53379         return t('background.none');
53380     };
53381
53382     source.imageryUsed = function() {
53383         return 'None';
53384     };
53385
53386     source.area = function() {
53387         return -1;  // sources in background pane are sorted by area
53388     };
53389
53390     return source;
53391 };
53392
53393
53394 rendererBackgroundSource.Custom = function(template) {
53395     var source = rendererBackgroundSource({ id: 'custom', template: template });
53396
53397     source.name = function() {
53398         return t('background.custom');
53399     };
53400
53401     source.imageryUsed = function() {
53402         return 'Custom (' + template + ')';
53403     };
53404
53405     source.area = function() {
53406         return -2;  // sources in background pane are sorted by area
53407     };
53408
53409     return source;
53410 };
53411
53412 function rendererTileLayer(context) {
53413     var tileSize = 256,
53414         tile = d3geoTile(),
53415         projection,
53416         cache = {},
53417         tileOrigin,
53418         z,
53419         transformProp = utilPrefixCSSProperty('Transform'),
53420         source = rendererBackgroundSource.None();
53421
53422
53423     // blacklist overlay tiles around Null Island..
53424     function nearNullIsland(x, y, z) {
53425         if (z >= 7) {
53426             var center = Math.pow(2, z - 1),
53427                 width = Math.pow(2, z - 6),
53428                 min$$1 = center - (width / 2),
53429                 max$$1 = center + (width / 2) - 1;
53430             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
53431         }
53432         return false;
53433     }
53434
53435
53436     function tileSizeAtZoom(d, z) {
53437         var epsilon = 0.002;
53438         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
53439     }
53440
53441
53442     function atZoom(t, distance) {
53443         var power = Math.pow(2, distance);
53444         return [
53445             Math.floor(t[0] * power),
53446             Math.floor(t[1] * power),
53447             t[2] + distance];
53448     }
53449
53450
53451     function lookUp(d) {
53452         for (var up = -1; up > -d[2]; up--) {
53453             var tile = atZoom(d, up);
53454             if (cache[source.url(tile)] !== false) {
53455                 return tile;
53456             }
53457         }
53458     }
53459
53460
53461     function uniqueBy(a, n) {
53462         var o = [], seen = {};
53463         for (var i = 0; i < a.length; i++) {
53464             if (seen[a[i][n]] === undefined) {
53465                 o.push(a[i]);
53466                 seen[a[i][n]] = true;
53467             }
53468         }
53469         return o;
53470     }
53471
53472
53473     function addSource(d) {
53474         d.push(source.url(d));
53475         return d;
53476     }
53477
53478
53479     // Update tiles based on current state of `projection`.
53480     function background(selection$$1) {
53481         tile.scale(projection.scale() * 2 * Math.PI)
53482             .translate(projection.translate());
53483
53484         tileOrigin = [
53485             projection.scale() * Math.PI - projection.translate()[0],
53486             projection.scale() * Math.PI - projection.translate()[1]];
53487
53488         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
53489
53490         render(selection$$1);
53491     }
53492
53493
53494     // Derive the tiles onscreen, remove those offscreen and position them.
53495     // Important that this part not depend on `projection` because it's
53496     // rentered when tiles load/error (see #644).
53497     function render(selection$$1) {
53498         var requests = [];
53499         var showDebug = context.getDebug('tile') && !source.overlay;
53500
53501         if (source.validZoom(z)) {
53502             tile().forEach(function(d) {
53503                 addSource(d);
53504                 if (d[3] === '') return;
53505                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
53506                 requests.push(d);
53507                 if (cache[d[3]] === false && lookUp(d)) {
53508                     requests.push(addSource(lookUp(d)));
53509                 }
53510             });
53511
53512             requests = uniqueBy(requests, 3).filter(function(r) {
53513                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
53514                     return false;
53515                 }
53516                 // don't re-request tiles which have failed in the past
53517                 return cache[r[3]] !== false;
53518             });
53519         }
53520
53521         var pixelOffset = [
53522             source.offset()[0] * Math.pow(2, z),
53523             source.offset()[1] * Math.pow(2, z)
53524         ];
53525
53526         function load(d) {
53527             cache[d[3]] = true;
53528             select(this)
53529                 .on('error', null)
53530                 .on('load', null)
53531                 .classed('tile-loaded', true);
53532             render(selection$$1);
53533         }
53534
53535         function error(d) {
53536             cache[d[3]] = false;
53537             select(this)
53538                 .on('error', null)
53539                 .on('load', null)
53540                 .remove();
53541             render(selection$$1);
53542         }
53543
53544         function imageTransform(d) {
53545             var _ts = tileSize * Math.pow(2, z - d[2]);
53546             var scale = tileSizeAtZoom(d, z);
53547             return 'translate(' +
53548                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
53549                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
53550                 'scale(' + scale + ',' + scale + ')';
53551         }
53552
53553         function debugTransform(d) {
53554             var _ts = tileSize * Math.pow(2, z - d[2]);
53555             var scale = tileSizeAtZoom(d, z);
53556             return 'translate(' +
53557                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
53558                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
53559         }
53560
53561
53562         var image = selection$$1.selectAll('img')
53563             .data(requests, function(d) { return d[3]; });
53564
53565         image.exit()
53566             .style(transformProp, imageTransform)
53567             .classed('tile-removing', true)
53568             .each(function() {
53569                 var tile = select(this);
53570                 window.setTimeout(function() {
53571                     if (tile.classed('tile-removing')) {
53572                         tile.remove();
53573                     }
53574                 }, 300);
53575             });
53576
53577         image.enter()
53578           .append('img')
53579             .attr('class', 'tile')
53580             .attr('src', function(d) { return d[3]; })
53581             .on('error', error)
53582             .on('load', load)
53583           .merge(image)
53584             .style(transformProp, imageTransform)
53585             .classed('tile-debug', showDebug)
53586             .classed('tile-removing', false);
53587
53588
53589         var debug = selection$$1.selectAll('.tile-label-debug')
53590             .data(showDebug ? requests : [], function(d) { return d[3]; });
53591
53592         debug.exit()
53593             .remove();
53594
53595         debug.enter()
53596           .append('div')
53597             .attr('class', 'tile-label-debug')
53598           .merge(debug)
53599             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
53600             .style(transformProp, debugTransform);
53601     }
53602
53603
53604     background.projection = function(_) {
53605         if (!arguments.length) return projection;
53606         projection = _;
53607         return background;
53608     };
53609
53610
53611     background.dimensions = function(_) {
53612         if (!arguments.length) return tile.size();
53613         tile.size(_);
53614         return background;
53615     };
53616
53617
53618     background.source = function(_) {
53619         if (!arguments.length) return source;
53620         source = _;
53621         cache = {};
53622         tile.scaleExtent(source.scaleExtent);
53623         return background;
53624     };
53625
53626
53627     return background;
53628 }
53629
53630 function rendererBackground(context) {
53631     var dispatch$$1 = dispatch('change'),
53632         baseLayer = rendererTileLayer(context).projection(context.projection),
53633         overlayLayers = [],
53634         backgroundSources;
53635
53636
53637     function findSource(id) {
53638         return lodash.find(backgroundSources, function(d) {
53639             return d.id && d.id === id;
53640         });
53641     }
53642
53643
53644     function background(selection$$1) {
53645         var base = selection$$1.selectAll('.layer-background')
53646             .data([0]);
53647
53648         base.enter()
53649             .insert('div', '.layer-data')
53650             .attr('class', 'layer layer-background')
53651             .merge(base)
53652             .call(baseLayer);
53653
53654         var overlays = selection$$1.selectAll('.layer-overlay')
53655             .data(overlayLayers, function(d) { return d.source().name(); });
53656
53657         overlays.exit()
53658             .remove();
53659
53660         overlays.enter()
53661             .insert('div', '.layer-data')
53662             .attr('class', 'layer layer-overlay')
53663             .merge(overlays)
53664             .each(function(layer) { select(this).call(layer); });
53665     }
53666
53667
53668     background.updateImagery = function() {
53669         var b = background.baseLayerSource(),
53670             o = overlayLayers
53671                 .filter(function (d) { return !d.source().isLocatorOverlay(); })
53672                 .map(function (d) { return d.source().id; })
53673                 .join(','),
53674             meters = geoOffsetToMeters(b.offset()),
53675             epsilon = 0.01,
53676             x = +meters[0].toFixed(2),
53677             y = +meters[1].toFixed(2),
53678             q = utilStringQs(window.location.hash.substring(1));
53679
53680         var id = b.id;
53681         if (id === 'custom') {
53682             id = 'custom:' + b.template;
53683         }
53684
53685         if (id) {
53686             q.background = id;
53687         } else {
53688             delete q.background;
53689         }
53690
53691         if (o) {
53692             q.overlays = o;
53693         } else {
53694             delete q.overlays;
53695         }
53696
53697         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
53698             q.offset = x + ',' + y;
53699         } else {
53700             delete q.offset;
53701         }
53702
53703         window.location.replace('#' + utilQsString(q, true));
53704
53705         var imageryUsed = [b.imageryUsed()];
53706
53707         overlayLayers
53708             .filter(function (d) { return !d.source().isLocatorOverlay(); })
53709             .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
53710
53711         var gpx = context.layers().layer('gpx');
53712         if (gpx && gpx.enabled() && gpx.hasGpx()) {
53713             imageryUsed.push('Local GPX');
53714         }
53715
53716         var mapillary_images = context.layers().layer('mapillary-images');
53717         if (mapillary_images && mapillary_images.enabled()) {
53718             imageryUsed.push('Mapillary Images');
53719         }
53720
53721         var mapillary_signs = context.layers().layer('mapillary-signs');
53722         if (mapillary_signs && mapillary_signs.enabled()) {
53723             imageryUsed.push('Mapillary Signs');
53724         }
53725
53726         context.history().imageryUsed(imageryUsed);
53727     };
53728
53729
53730     background.sources = function(extent$$1) {
53731         return backgroundSources.filter(function(source) {
53732             return source.intersects(extent$$1);
53733         });
53734     };
53735
53736
53737     background.dimensions = function(_) {
53738         if (!_) return;
53739         baseLayer.dimensions(_);
53740
53741         overlayLayers.forEach(function(layer) {
53742             layer.dimensions(_);
53743         });
53744     };
53745
53746
53747     background.baseLayerSource = function(d) {
53748         if (!arguments.length) return baseLayer.source();
53749
53750         // test source against OSM imagery blacklists..
53751         var blacklists = context.connection().imageryBlacklists();
53752
53753         var fail = false,
53754             tested = 0,
53755             regex, i;
53756
53757         for (i = 0; i < blacklists.length; i++) {
53758             try {
53759                 regex = new RegExp(blacklists[i]);
53760                 fail = regex.test(d.template);
53761                 tested++;
53762                 if (fail) break;
53763             } catch (e) {
53764                 /* noop */
53765             }
53766         }
53767
53768         // ensure at least one test was run.
53769         if (!tested) {
53770             regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
53771             fail = regex.test(d.template);
53772         }
53773
53774         baseLayer.source(!fail ? d : rendererBackgroundSource.None());
53775         dispatch$$1.call('change');
53776         background.updateImagery();
53777         return background;
53778     };
53779
53780
53781     background.bing = function() {
53782         background.baseLayerSource(findSource('Bing'));
53783     };
53784
53785
53786     background.showsLayer = function(d) {
53787         return d.id === baseLayer.source().id ||
53788             overlayLayers.some(function(layer) { return d.id === layer.source().id; });
53789     };
53790
53791
53792     background.overlayLayerSources = function() {
53793         return overlayLayers.map(function (l) { return l.source(); });
53794     };
53795
53796
53797     background.toggleOverlayLayer = function(d) {
53798         var layer;
53799
53800         for (var i = 0; i < overlayLayers.length; i++) {
53801             layer = overlayLayers[i];
53802             if (layer.source() === d) {
53803                 overlayLayers.splice(i, 1);
53804                 dispatch$$1.call('change');
53805                 background.updateImagery();
53806                 return;
53807             }
53808         }
53809
53810         layer = rendererTileLayer(context)
53811             .source(d)
53812             .projection(context.projection)
53813             .dimensions(baseLayer.dimensions());
53814
53815         overlayLayers.push(layer);
53816         dispatch$$1.call('change');
53817         background.updateImagery();
53818     };
53819
53820
53821     background.nudge = function(d, zoom$$1) {
53822         baseLayer.source().nudge(d, zoom$$1);
53823         dispatch$$1.call('change');
53824         background.updateImagery();
53825         return background;
53826     };
53827
53828
53829     background.offset = function(d) {
53830         if (!arguments.length) return baseLayer.source().offset();
53831         baseLayer.source().offset(d);
53832         dispatch$$1.call('change');
53833         background.updateImagery();
53834         return background;
53835     };
53836
53837
53838     background.init = function() {
53839         function parseMap(qmap) {
53840             if (!qmap) return false;
53841             var args = qmap.split('/').map(Number);
53842             if (args.length < 3 || args.some(isNaN)) return false;
53843             return geoExtent$$1([args[2], args[1]]);
53844         }
53845
53846         var dataImagery = data.imagery || [],
53847             q = utilStringQs(window.location.hash.substring(1)),
53848             chosen = q.background || q.layer,
53849             extent$$1 = parseMap(q.map),
53850             best;
53851
53852         backgroundSources = dataImagery.map(function(source) {
53853             if (source.type === 'bing') {
53854                 return rendererBackgroundSource.Bing(source, dispatch$$1);
53855             } else {
53856                 return rendererBackgroundSource(source);
53857             }
53858         });
53859
53860         backgroundSources.unshift(rendererBackgroundSource.None());
53861
53862         if (!chosen && extent$$1) {
53863             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
53864         }
53865
53866         if (chosen && chosen.indexOf('custom:') === 0) {
53867             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
53868         } else {
53869             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
53870         }
53871
53872         var locator = lodash.find(backgroundSources, function(d) {
53873             return d.overlay && d.default;
53874         });
53875
53876         if (locator) {
53877             background.toggleOverlayLayer(locator);
53878         }
53879
53880         var overlays = (q.overlays || '').split(',');
53881         overlays.forEach(function(overlay) {
53882             overlay = findSource(overlay);
53883             if (overlay) {
53884                 background.toggleOverlayLayer(overlay);
53885             }
53886         });
53887
53888         if (q.gpx) {
53889             var gpx = context.layers().layer('gpx');
53890             if (gpx) {
53891                 gpx.url(q.gpx);
53892             }
53893         }
53894
53895         if (q.offset) {
53896             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
53897                 return !isNaN(n) && n;
53898             });
53899
53900             if (offset.length === 2) {
53901                 background.offset(geoMetersToOffset(offset));
53902             }
53903         }
53904     };
53905
53906
53907     return utilRebind(background, dispatch$$1, 'on');
53908 }
53909
53910 function rendererFeatures(context) {
53911     var traffic_roads = {
53912         'motorway': true,
53913         'motorway_link': true,
53914         'trunk': true,
53915         'trunk_link': true,
53916         'primary': true,
53917         'primary_link': true,
53918         'secondary': true,
53919         'secondary_link': true,
53920         'tertiary': true,
53921         'tertiary_link': true,
53922         'residential': true,
53923         'unclassified': true,
53924         'living_street': true
53925     };
53926
53927     var service_roads = {
53928         'service': true,
53929         'road': true,
53930         'track': true
53931     };
53932
53933     var paths = {
53934         'path': true,
53935         'footway': true,
53936         'cycleway': true,
53937         'bridleway': true,
53938         'steps': true,
53939         'pedestrian': true,
53940         'corridor': true
53941     };
53942
53943     var past_futures = {
53944         'proposed': true,
53945         'construction': true,
53946         'abandoned': true,
53947         'dismantled': true,
53948         'disused': true,
53949         'razed': true,
53950         'demolished': true,
53951         'obliterated': true
53952     };
53953
53954     var dispatch$$1 = dispatch('change', 'redraw'),
53955         _cullFactor = 1,
53956         _cache = {},
53957         _features = {},
53958         _stats = {},
53959         _keys = [],
53960         _hidden = [];
53961
53962
53963     function update() {
53964         _hidden = features.hidden();
53965         dispatch$$1.call('change');
53966         dispatch$$1.call('redraw');
53967     }
53968
53969
53970     function defineFeature(k, filter, max$$1) {
53971         _keys.push(k);
53972         _features[k] = {
53973             filter: filter,
53974             enabled: true,   // whether the user wants it enabled..
53975             count: 0,
53976             currentMax: (max$$1 || Infinity),
53977             defaultMax: (max$$1 || Infinity),
53978             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
53979             disable: function() { this.enabled = false; this.currentMax = 0; },
53980             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
53981             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
53982         };
53983     }
53984
53985
53986     defineFeature('points', function isPoint(entity, resolver, geometry) {
53987         return geometry === 'point';
53988     }, 200);
53989
53990     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53991         return traffic_roads[entity.tags.highway];
53992     });
53993
53994     defineFeature('service_roads', function isServiceRoad(entity) {
53995         return service_roads[entity.tags.highway];
53996     });
53997
53998     defineFeature('paths', function isPath(entity) {
53999         return paths[entity.tags.highway];
54000     });
54001
54002     defineFeature('buildings', function isBuilding(entity) {
54003         return (
54004             !!entity.tags['building:part'] ||
54005             (!!entity.tags.building && entity.tags.building !== 'no') ||
54006             entity.tags.amenity === 'shelter' ||
54007             entity.tags.parking === 'multi-storey' ||
54008             entity.tags.parking === 'sheds' ||
54009             entity.tags.parking === 'carports' ||
54010             entity.tags.parking === 'garage_boxes'
54011         );
54012     }, 250);
54013
54014     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
54015         return geometry === 'area' &&
54016             !_features.buildings.filter(entity) &&
54017             !_features.water.filter(entity);
54018     });
54019
54020     defineFeature('boundaries', function isBoundary(entity) {
54021         return !!entity.tags.boundary;
54022     });
54023
54024     defineFeature('water', function isWater(entity) {
54025         return (
54026             !!entity.tags.waterway ||
54027             entity.tags.natural === 'water' ||
54028             entity.tags.natural === 'coastline' ||
54029             entity.tags.natural === 'bay' ||
54030             entity.tags.landuse === 'pond' ||
54031             entity.tags.landuse === 'basin' ||
54032             entity.tags.landuse === 'reservoir' ||
54033             entity.tags.landuse === 'salt_pond'
54034         );
54035     });
54036
54037     defineFeature('rail', function isRail(entity) {
54038         return (
54039             !!entity.tags.railway ||
54040             entity.tags.landuse === 'railway'
54041         ) && !(
54042             traffic_roads[entity.tags.highway] ||
54043             service_roads[entity.tags.highway] ||
54044             paths[entity.tags.highway]
54045         );
54046     });
54047
54048     defineFeature('power', function isPower(entity) {
54049         return !!entity.tags.power;
54050     });
54051
54052     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
54053     defineFeature('past_future', function isPastFuture(entity) {
54054         if (
54055             traffic_roads[entity.tags.highway] ||
54056             service_roads[entity.tags.highway] ||
54057             paths[entity.tags.highway]
54058         ) { return false; }
54059
54060         var strings = Object.keys(entity.tags);
54061
54062         for (var i = 0; i < strings.length; i++) {
54063             var s = strings[i];
54064             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
54065         }
54066         return false;
54067     });
54068
54069     // Lines or areas that don't match another feature filter.
54070     // IMPORTANT: The 'others' feature must be the last one defined,
54071     //   so that code in getMatches can skip this test if `hasMatch = true`
54072     defineFeature('others', function isOther(entity, resolver, geometry) {
54073         return (geometry === 'line' || geometry === 'area');
54074     });
54075
54076
54077     function features() {}
54078
54079
54080     features.features = function() {
54081         return _features;
54082     };
54083
54084
54085     features.keys = function() {
54086         return _keys;
54087     };
54088
54089
54090     features.enabled = function(k) {
54091         if (!arguments.length) {
54092             return _keys.filter(function(k) { return _features[k].enabled; });
54093         }
54094         return _features[k] && _features[k].enabled;
54095     };
54096
54097
54098     features.disabled = function(k) {
54099         if (!arguments.length) {
54100             return _keys.filter(function(k) { return !_features[k].enabled; });
54101         }
54102         return _features[k] && !_features[k].enabled;
54103     };
54104
54105
54106     features.hidden = function(k) {
54107         if (!arguments.length) {
54108             return _keys.filter(function(k) { return _features[k].hidden(); });
54109         }
54110         return _features[k] && _features[k].hidden();
54111     };
54112
54113
54114     features.autoHidden = function(k) {
54115         if (!arguments.length) {
54116             return _keys.filter(function(k) { return _features[k].autoHidden(); });
54117         }
54118         return _features[k] && _features[k].autoHidden();
54119     };
54120
54121
54122     features.enable = function(k) {
54123         if (_features[k] && !_features[k].enabled) {
54124             _features[k].enable();
54125             update();
54126         }
54127     };
54128
54129
54130     features.disable = function(k) {
54131         if (_features[k] && _features[k].enabled) {
54132             _features[k].disable();
54133             update();
54134         }
54135     };
54136
54137
54138     features.toggle = function(k) {
54139         if (_features[k]) {
54140             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
54141             update();
54142         }
54143     };
54144
54145
54146     features.resetStats = function() {
54147         for (var i = 0; i < _keys.length; i++) {
54148             _features[_keys[i]].count = 0;
54149         }
54150         dispatch$$1.call('change');
54151     };
54152
54153
54154     features.gatherStats = function(d, resolver, dimensions) {
54155         var needsRedraw = false,
54156             type = lodash.groupBy(d, function(ent) { return ent.type; }),
54157             entities = [].concat(type.relation || [], type.way || [], type.node || []),
54158             currHidden, geometry, matches, i, j;
54159
54160         for (i = 0; i < _keys.length; i++) {
54161             _features[_keys[i]].count = 0;
54162         }
54163
54164         // adjust the threshold for point/building culling based on viewport size..
54165         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
54166         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
54167
54168         for (i = 0; i < entities.length; i++) {
54169             geometry = entities[i].geometry(resolver);
54170             if (!(geometry === 'vertex' || geometry === 'relation')) {
54171                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
54172                 for (j = 0; j < matches.length; j++) {
54173                     _features[matches[j]].count++;
54174                 }
54175             }
54176         }
54177
54178         currHidden = features.hidden();
54179         if (currHidden !== _hidden) {
54180             _hidden = currHidden;
54181             needsRedraw = true;
54182             dispatch$$1.call('change');
54183         }
54184
54185         return needsRedraw;
54186     };
54187
54188
54189     features.stats = function() {
54190         for (var i = 0; i < _keys.length; i++) {
54191             _stats[_keys[i]] = _features[_keys[i]].count;
54192         }
54193
54194         return _stats;
54195     };
54196
54197
54198     features.clear = function(d) {
54199         for (var i = 0; i < d.length; i++) {
54200             features.clearEntity(d[i]);
54201         }
54202     };
54203
54204
54205     features.clearEntity = function(entity) {
54206         delete _cache[osmEntity$$1.key(entity)];
54207     };
54208
54209
54210     features.reset = function() {
54211         _cache = {};
54212     };
54213
54214
54215     features.getMatches = function(entity, resolver, geometry) {
54216         if (geometry === 'vertex' || geometry === 'relation') return {};
54217
54218         var ent = osmEntity$$1.key(entity);
54219         if (!_cache[ent]) {
54220             _cache[ent] = {};
54221         }
54222
54223         if (!_cache[ent].matches) {
54224             var matches = {},
54225                 hasMatch = false;
54226
54227             for (var i = 0; i < _keys.length; i++) {
54228                 if (_keys[i] === 'others') {
54229                     if (hasMatch) continue;
54230
54231                     // Multipolygon members:
54232                     // If an entity...
54233                     //   1. is a way that hasn't matched other 'interesting' feature rules,
54234                     //   2. and it belongs to a single parent multipolygon relation
54235                     // ...then match whatever feature rules the parent multipolygon has matched.
54236                     // see #2548, #2887
54237                     //
54238                     // IMPORTANT:
54239                     // For this to work, getMatches must be called on relations before ways.
54240                     //
54241                     if (entity.type === 'way') {
54242                         var parents = features.getParents(entity, resolver, geometry);
54243                         if (parents.length === 1 && parents[0].isMultipolygon()) {
54244                             var pkey = osmEntity$$1.key(parents[0]);
54245                             if (_cache[pkey] && _cache[pkey].matches) {
54246                                 matches = lodash.clone(_cache[pkey].matches);
54247                                 continue;
54248                             }
54249                         }
54250                     }
54251                 }
54252
54253                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
54254                     matches[_keys[i]] = hasMatch = true;
54255                 }
54256             }
54257             _cache[ent].matches = matches;
54258         }
54259
54260         return _cache[ent].matches;
54261     };
54262
54263
54264     features.getParents = function(entity, resolver, geometry) {
54265         if (geometry === 'point') return [];
54266
54267         var ent = osmEntity$$1.key(entity);
54268         if (!_cache[ent]) {
54269             _cache[ent] = {};
54270         }
54271
54272         if (!_cache[ent].parents) {
54273             var parents = [];
54274             if (geometry === 'vertex') {
54275                 parents = resolver.parentWays(entity);
54276             } else {   // 'line', 'area', 'relation'
54277                 parents = resolver.parentRelations(entity);
54278             }
54279             _cache[ent].parents = parents;
54280         }
54281         return _cache[ent].parents;
54282     };
54283
54284
54285     features.isHiddenFeature = function(entity, resolver, geometry) {
54286         if (!_hidden.length) return false;
54287         if (!entity.version) return false;
54288
54289         var matches = features.getMatches(entity, resolver, geometry);
54290
54291         for (var i = 0; i < _hidden.length; i++) {
54292             if (matches[_hidden[i]]) return true;
54293         }
54294         return false;
54295     };
54296
54297
54298     features.isHiddenChild = function(entity, resolver, geometry) {
54299         if (!_hidden.length) return false;
54300         if (!entity.version || geometry === 'point') return false;
54301
54302         var parents = features.getParents(entity, resolver, geometry);
54303         if (!parents.length) return false;
54304
54305         for (var i = 0; i < parents.length; i++) {
54306             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
54307                 return false;
54308             }
54309         }
54310         return true;
54311     };
54312
54313
54314     features.hasHiddenConnections = function(entity, resolver) {
54315         if (!_hidden.length) return false;
54316         var childNodes, connections;
54317
54318         if (entity.type === 'midpoint') {
54319             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
54320             connections = [];
54321         } else {
54322             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
54323             connections = features.getParents(entity, resolver, entity.geometry(resolver));
54324         }
54325
54326         // gather ways connected to child nodes..
54327         connections = lodash.reduce(childNodes, function(result, e) {
54328             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
54329         }, connections);
54330
54331         return connections.length ? lodash.some(connections, function(e) {
54332             return features.isHidden(e, resolver, e.geometry(resolver));
54333         }) : false;
54334     };
54335
54336
54337     features.isHidden = function(entity, resolver, geometry) {
54338         if (!_hidden.length) return false;
54339         if (!entity.version) return false;
54340
54341         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
54342         return fn(entity, resolver, geometry);
54343     };
54344
54345
54346     features.filter = function(d, resolver) {
54347         if (!_hidden.length) return d;
54348
54349         var result = [];
54350         for (var i = 0; i < d.length; i++) {
54351             var entity = d[i];
54352             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
54353                 result.push(entity);
54354             }
54355         }
54356         return result;
54357     };
54358
54359
54360     return utilRebind(features, dispatch$$1, 'on');
54361 }
54362
54363 function utilBindOnce(target, type, listener, capture) {
54364     var typeOnce = type + '.once';
54365     function one() {
54366         target.on(typeOnce, null);
54367         listener.apply(this, arguments);
54368     }
54369     target.on(typeOnce, one, capture);
54370     return this;
54371 }
54372
54373 function rendererMap(context) {
54374
54375     var dimensions = [1, 1],
54376         dispatch$$1 = dispatch('move', 'drawn'),
54377         projection = context.projection,
54378         dblclickEnabled = true,
54379         redrawEnabled = true,
54380         transformStart = projection.transform(),
54381         transformed = false,
54382         minzoom = 0,
54383         drawLayers = svgLayers(projection, context),
54384         drawPoints = svgPoints$$1(projection, context),
54385         drawVertices = svgVertices$$1(projection, context),
54386         drawLines = svgLines$$1(projection),
54387         drawAreas = svgAreas$$1(projection, context),
54388         drawMidpoints = svgMidpoints$$1(projection, context),
54389         drawLabels = svgLabels(projection, context),
54390         supersurface = select(null),
54391         wrapper = select(null),
54392         surface = select(null),
54393         mouse$$1,
54394         mousemove;
54395
54396     var zoom$$1 = zoom$1()
54397             .scaleExtent([ztok(2), ztok(24)])
54398             .interpolate(value$1)
54399             .filter(zoomEventFilter)
54400             .on('zoom', zoomPan);
54401
54402     var _selection = select(null);
54403
54404
54405     function map$$1(selection$$1) {
54406
54407         _selection = selection$$1;
54408
54409         context
54410             .on('change.map', immediateRedraw);
54411
54412         context.connection()
54413             .on('change.map', immediateRedraw);
54414
54415         context.history()
54416             .on('change.map', immediateRedraw)
54417             .on('undone.context redone.context', function(stack$$1) {
54418                 var followSelected = false;
54419                 if (Array.isArray(stack$$1.selectedIDs)) {
54420                     followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
54421                     context.enter(
54422                         modeSelect(context, stack$$1.selectedIDs).suppressMenu(true).follow(followSelected)
54423                     );
54424                 }
54425                 if (!followSelected && stack$$1.transform) {
54426                     map$$1.transformEase(stack$$1.transform);
54427                 }
54428             });
54429
54430         context.background()
54431             .on('change.map', immediateRedraw);
54432
54433         context.features()
54434             .on('redraw.map', immediateRedraw);
54435
54436         drawLayers
54437             .on('change.map', function() {
54438                 context.background().updateImagery();
54439                 immediateRedraw();
54440             });
54441
54442         selection$$1
54443             .on('dblclick.map', dblClick)
54444             .call(zoom$$1)
54445             .call(zoom$$1.transform, projection.transform());
54446
54447         supersurface = selection$$1.append('div')
54448             .attr('id', 'supersurface')
54449             .call(utilSetTransform, 0, 0);
54450
54451         // Need a wrapper div because Opera can't cope with an absolutely positioned
54452         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
54453         wrapper = supersurface
54454             .append('div')
54455             .attr('class', 'layer layer-data');
54456
54457         map$$1.surface = surface = wrapper
54458             .call(drawLayers)
54459             .selectAll('.surface')
54460             .attr('id', 'surface');
54461
54462         surface
54463             .call(drawLabels.observe)
54464             .on('mousedown.zoom', function() {
54465                 if (event.button === 2) {
54466                     event.stopPropagation();
54467                 }
54468             }, true)
54469             .on('mouseup.zoom', function() {
54470                 if (resetTransform()) immediateRedraw();
54471             })
54472             .on('mousemove.map', function() {
54473                 mousemove = event;
54474             })
54475             .on('mouseover.vertices', function() {
54476                 if (map$$1.editable() && !transformed) {
54477                     var hover = event.target.__data__;
54478                     surface.selectAll('.data-layer-osm')
54479                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54480                     dispatch$$1.call('drawn', this, {full: false});
54481                 }
54482             })
54483             .on('mouseout.vertices', function() {
54484                 if (map$$1.editable() && !transformed) {
54485                     var hover = event.relatedTarget && event.relatedTarget.__data__;
54486                     surface.selectAll('.data-layer-osm')
54487                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54488                     dispatch$$1.call('drawn', this, {full: false});
54489                 }
54490             });
54491
54492         supersurface
54493             .call(context.background());
54494
54495         context.on('enter.map', function() {
54496             if (map$$1.editable() && !transformed) {
54497                 var all = context.intersects(map$$1.extent()),
54498                     filter = utilFunctor(true),
54499                     graph = context.graph();
54500
54501                 all = context.features().filter(all, graph);
54502                 surface.selectAll('.data-layer-osm')
54503                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
54504                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
54505                 dispatch$$1.call('drawn', this, {full: false});
54506             }
54507         });
54508
54509         map$$1.dimensions(utilGetDimensions(selection$$1));
54510     }
54511
54512
54513     function zoomEventFilter() {
54514         // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
54515         // Intercept `mousedown` and check if there is an orphaned zoom gesture.
54516         // This can happen if a previous `mousedown` occurred without a `mouseup`.
54517         // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
54518         // so that d3-zoom won't stop propagation of new `mousedown` events.
54519         if (event.type === 'mousedown') {
54520             var hasOrphan = false;
54521             var listeners = window.__on;
54522             for (var i = 0; i < listeners.length; i++) {
54523                 var listener = listeners[i];
54524                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
54525                     hasOrphan = true;
54526                     break;
54527                 }
54528             }
54529             if (hasOrphan) {
54530                 var event$$1 = window.CustomEvent;
54531                 if (event$$1) {
54532                     event$$1 = new event$$1('mouseup');
54533                 } else {
54534                     event$$1 = window.document.createEvent('Event');
54535                     event$$1.initEvent('mouseup', false, false);
54536                 }
54537                 // Event needs to be dispatched with an event.view property.
54538                 event$$1.view = window;
54539                 window.dispatchEvent(event$$1);
54540             }
54541         }
54542
54543         return event.button !== 2;   // ignore right clicks
54544     }
54545
54546
54547     function ztok(z) {
54548         return 256 * Math.pow(2, z);
54549     }
54550
54551     function ktoz(k) {
54552         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
54553     }
54554
54555     function pxCenter() {
54556         return [dimensions[0] / 2, dimensions[1] / 2];
54557     }
54558
54559
54560     function drawVector(difference, extent$$1) {
54561         var graph = context.graph(),
54562             features = context.features(),
54563             all = context.intersects(map$$1.extent()),
54564             data, filter;
54565
54566         if (difference) {
54567             var complete = difference.complete(map$$1.extent());
54568             data = lodash.compact(lodash.values(complete));
54569             filter = function(d) { return d.id in complete; };
54570             features.clear(data);
54571
54572         } else {
54573             // force a full redraw if gatherStats detects that a feature
54574             // should be auto-hidden (e.g. points or buildings)..
54575             if (features.gatherStats(all, graph, dimensions)) {
54576                 extent$$1 = undefined;
54577             }
54578
54579             if (extent$$1) {
54580                 data = context.intersects(map$$1.extent().intersection(extent$$1));
54581                 var set$$1 = set$2(lodash.map(data, 'id'));
54582                 filter = function(d) { return set$$1.has(d.id); };
54583
54584             } else {
54585                 data = all;
54586                 filter = utilFunctor(true);
54587             }
54588         }
54589
54590         data = features.filter(data, graph);
54591
54592         surface.selectAll('.data-layer-osm')
54593             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
54594             .call(drawLines, graph, data, filter)
54595             .call(drawAreas, graph, data, filter)
54596             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
54597             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
54598             .call(drawPoints, graph, data, filter);
54599
54600         dispatch$$1.call('drawn', this, {full: true});
54601     }
54602
54603
54604     function editOff() {
54605         context.features().resetStats();
54606         surface.selectAll('.layer-osm *').remove();
54607         dispatch$$1.call('drawn', this, {full: true});
54608     }
54609
54610
54611     function dblClick() {
54612         if (!dblclickEnabled) {
54613             event.preventDefault();
54614             event.stopImmediatePropagation();
54615         }
54616     }
54617
54618
54619     function zoomPan(manualEvent) {
54620         var eventTransform = (manualEvent || event).transform;
54621
54622         if (transformStart.x === eventTransform.x &&
54623             transformStart.y === eventTransform.y &&
54624             transformStart.k === eventTransform.k) {
54625             return;  // no change
54626         }
54627
54628         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
54629             surface.interrupt();
54630             uiFlash(context.container())
54631                 .select('.content')
54632                 .text(t('cannot_zoom'));
54633             setZoom(context.minEditableZoom(), true);
54634             queueRedraw();
54635             dispatch$$1.call('move', this, map$$1);
54636             return;
54637         }
54638
54639         projection.transform(eventTransform);
54640
54641         var scale = eventTransform.k / transformStart.k,
54642             tX = (eventTransform.x / scale - transformStart.x) * scale,
54643             tY = (eventTransform.y / scale - transformStart.y) * scale;
54644
54645         transformed = true;
54646         utilSetTransform(supersurface, tX, tY, scale);
54647         queueRedraw();
54648
54649         dispatch$$1.call('move', this, map$$1);
54650     }
54651
54652
54653     function resetTransform() {
54654         if (!transformed) return false;
54655
54656         surface.selectAll('.radial-menu').interrupt().remove();
54657         utilSetTransform(supersurface, 0, 0);
54658         transformed = false;
54659         return true;
54660     }
54661
54662
54663     function redraw(difference, extent$$1) {
54664         if (surface.empty() || !redrawEnabled) return;
54665
54666         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
54667         // It would result in artifacts where differenced entities are redrawn with
54668         // one transform and unchanged entities with another.
54669         if (resetTransform()) {
54670             difference = extent$$1 = undefined;
54671         }
54672
54673         var z = String(~~map$$1.zoom());
54674         if (surface.attr('data-zoom') !== z) {
54675             surface.attr('data-zoom', z)
54676                 .classed('low-zoom', z <= 16);
54677         }
54678
54679         if (!difference) {
54680             supersurface.call(context.background());
54681         }
54682
54683         wrapper
54684             .call(drawLayers);
54685
54686         // OSM
54687         if (map$$1.editable()) {
54688             context.loadTiles(projection, dimensions);
54689             drawVector(difference, extent$$1);
54690         } else {
54691             editOff();
54692         }
54693
54694         transformStart = projection.transform();
54695
54696         return map$$1;
54697     }
54698
54699
54700     var queueRedraw = lodash.throttle(redraw, 750);
54701
54702
54703     var immediateRedraw = function(difference, extent$$1) {
54704         if (!difference && !extent$$1) queueRedraw.cancel();
54705         redraw(difference, extent$$1);
54706     };
54707
54708
54709     function pointLocation(p) {
54710         var translate = projection.translate(),
54711             scale = projection.scale() * 2 * Math.PI;
54712         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
54713     }
54714
54715
54716     function locationPoint(l) {
54717         var translate = projection.translate(),
54718             scale = projection.scale() * 2 * Math.PI;
54719         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
54720     }
54721
54722
54723     map$$1.mouse = function() {
54724         var event$$1 = mousemove || event;
54725         if (event$$1) {
54726             var s;
54727             while ((s = event$$1.sourceEvent)) { event$$1 = s; }
54728             return mouse$$1(event$$1);
54729         }
54730         return null;
54731     };
54732
54733
54734     map$$1.mouseCoordinates = function() {
54735         return projection.invert(map$$1.mouse());
54736     };
54737
54738
54739     map$$1.dblclickEnable = function(_) {
54740         if (!arguments.length) return dblclickEnabled;
54741         dblclickEnabled = _;
54742         return map$$1;
54743     };
54744
54745
54746     map$$1.redrawEnable = function(_) {
54747         if (!arguments.length) return redrawEnabled;
54748         redrawEnabled = _;
54749         return map$$1;
54750     };
54751
54752
54753     function setTransform(t2, duration, force) {
54754         var t$$1 = projection.transform();
54755         if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
54756             return false;
54757         }
54758
54759         if (duration) {
54760             _selection
54761                 .transition()
54762                 .duration(duration)
54763                 .on('start', function() { map$$1.startEase(); })
54764                 .call(zoom$$1.transform, identity$9.translate(t2.x, t2.y).scale(t2.k));
54765         } else {
54766             projection.transform(t2);
54767             transformStart = t2;
54768             _selection.call(zoom$$1.transform, transformStart);
54769         }
54770     }
54771
54772
54773     function setZoom(z2, force, duration) {
54774         if (z2 === map$$1.zoom() && !force) {
54775             return false;
54776         }
54777
54778         var k = projection.scale(),
54779             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
54780             center = pxCenter(),
54781             l = pointLocation(center);
54782
54783         projection.scale(k2);
54784
54785         var t$$1 = projection.translate();
54786         l = locationPoint(l);
54787
54788         t$$1[0] += center[0] - l[0];
54789         t$$1[1] += center[1] - l[1];
54790
54791         if (duration) {
54792             projection.scale(k);  // reset scale
54793             _selection
54794                 .transition()
54795                 .duration(duration)
54796                 .on('start', function() { map$$1.startEase(); })
54797                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k2));
54798         } else {
54799             projection.translate(t$$1);
54800             transformStart = projection.transform();
54801             _selection.call(zoom$$1.transform, transformStart);
54802         }
54803
54804         return true;
54805     }
54806
54807
54808     function setCenter(loc2, duration) {
54809         var c = map$$1.center();
54810         if (loc2[0] === c[0] && loc2[1] === c[1]) {
54811             return false;
54812         }
54813
54814         var t$$1 = projection.translate(),
54815             k = projection.scale(),
54816             pxC = pxCenter(),
54817             ll = projection(loc2);
54818
54819         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
54820         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
54821
54822         if (duration) {
54823             _selection
54824                 .transition()
54825                 .duration(duration)
54826                 .on('start', function() { map$$1.startEase(); })
54827                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54828         } else {
54829             projection.translate(t$$1);
54830             transformStart = projection.transform();
54831             _selection.call(zoom$$1.transform, transformStart);
54832         }
54833
54834         return true;
54835     }
54836
54837
54838     map$$1.pan = function(delta, duration) {
54839         var t$$1 = projection.translate(),
54840             k = projection.scale();
54841
54842         t$$1[0] += delta[0];
54843         t$$1[1] += delta[1];
54844
54845         if (duration) {
54846             _selection
54847                 .transition()
54848                 .duration(duration)
54849                 .on('start', function() { map$$1.startEase(); })
54850                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54851         } else {
54852             projection.translate(t$$1);
54853             transformStart = projection.transform();
54854             _selection.call(zoom$$1.transform, transformStart);
54855             dispatch$$1.call('move', this, map$$1);
54856             immediateRedraw();
54857         }
54858
54859         return map$$1;
54860     };
54861
54862
54863     map$$1.dimensions = function(_) {
54864         if (!arguments.length) return dimensions;
54865         var center = map$$1.center();
54866         dimensions = _;
54867         drawLayers.dimensions(dimensions);
54868         context.background().dimensions(dimensions);
54869         projection.clipExtent([[0, 0], dimensions]);
54870         mouse$$1 = utilFastMouse(supersurface.node());
54871         setCenter(center);
54872
54873         queueRedraw();
54874         return map$$1;
54875     };
54876
54877
54878     function zoomIn(delta) {
54879         setZoom(~~map$$1.zoom() + delta, true, 250);
54880     }
54881
54882     function zoomOut(delta) {
54883         setZoom(~~map$$1.zoom() - delta, true, 250);
54884     }
54885
54886     map$$1.zoomIn = function() { zoomIn(1); };
54887     map$$1.zoomInFurther = function() { zoomIn(4); };
54888
54889     map$$1.zoomOut = function() { zoomOut(1); };
54890     map$$1.zoomOutFurther = function() { zoomOut(4); };
54891
54892
54893     map$$1.center = function(loc2) {
54894         if (!arguments.length) {
54895             return projection.invert(pxCenter());
54896         }
54897
54898         if (setCenter(loc2)) {
54899             dispatch$$1.call('move', this, map$$1);
54900         }
54901
54902         queueRedraw();
54903         return map$$1;
54904     };
54905
54906
54907     map$$1.zoom = function(z2) {
54908         if (!arguments.length) {
54909             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
54910         }
54911
54912         if (z2 < minzoom) {
54913             surface.interrupt();
54914             uiFlash(context.container())
54915                 .select('.content')
54916                 .text(t('cannot_zoom'));
54917             z2 = context.minEditableZoom();
54918         }
54919
54920         if (setZoom(z2)) {
54921             dispatch$$1.call('move', this, map$$1);
54922         }
54923
54924         queueRedraw();
54925         return map$$1;
54926     };
54927
54928
54929     map$$1.zoomTo = function(entity, zoomLimits) {
54930         var extent$$1 = entity.extent(context.graph());
54931         if (!isFinite(extent$$1.area())) return;
54932
54933         var z2 = map$$1.trimmedExtentZoom(extent$$1);
54934         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
54935         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
54936     };
54937
54938
54939     map$$1.centerZoom = function(loc2, z2) {
54940         var centered = setCenter(loc2),
54941             zoomed   = setZoom(z2);
54942
54943         if (centered || zoomed) {
54944             dispatch$$1.call('move', this, map$$1);
54945         }
54946
54947         queueRedraw();
54948         return map$$1;
54949     };
54950
54951
54952     map$$1.centerEase = function(loc2, duration) {
54953         duration = duration || 250;
54954         setCenter(loc2, duration);
54955         return map$$1;
54956     };
54957
54958
54959     map$$1.zoomEase = function(z2, duration) {
54960         duration = duration || 250;
54961         setZoom(z2, false, duration);
54962         return map$$1;
54963     };
54964
54965
54966     map$$1.transformEase = function(t2, duration) {
54967         duration = duration || 250;
54968         setTransform(t2, duration, false);
54969         return map$$1;
54970     };
54971
54972
54973     map$$1.startEase = function() {
54974         utilBindOnce(surface, 'mousedown.ease', function() {
54975             map$$1.cancelEase();
54976         });
54977         return map$$1;
54978     };
54979
54980
54981     map$$1.cancelEase = function() {
54982         _selection.interrupt();
54983         return map$$1;
54984     };
54985
54986
54987     map$$1.extent = function(_) {
54988         if (!arguments.length) {
54989             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
54990                                  projection.invert([dimensions[0], 0]));
54991         } else {
54992             var extent$$1 = geoExtent$$1(_);
54993             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
54994         }
54995     };
54996
54997
54998     map$$1.trimmedExtent = function(_) {
54999         if (!arguments.length) {
55000             var headerY = 60, footerY = 30, pad = 10;
55001             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
55002                                  projection.invert([dimensions[0] - pad, headerY + pad]));
55003         } else {
55004             var extent$$1 = geoExtent$$1(_);
55005             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
55006         }
55007     };
55008
55009
55010     function calcZoom(extent$$1, dim) {
55011         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
55012             br = projection([extent$$1[1][0], extent$$1[0][1]]);
55013
55014         // Calculate maximum zoom that fits extent
55015         var hFactor = (br[0] - tl[0]) / dim[0],
55016             vFactor = (br[1] - tl[1]) / dim[1],
55017             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
55018             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
55019             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
55020
55021         return newZoom;
55022     }
55023
55024
55025     map$$1.extentZoom = function(_) {
55026         return calcZoom(geoExtent$$1(_), dimensions);
55027     };
55028
55029
55030     map$$1.trimmedExtentZoom = function(_) {
55031         var trimY = 120, trimX = 40,
55032             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
55033         return calcZoom(geoExtent$$1(_), trimmed);
55034     };
55035
55036
55037     map$$1.editable = function() {
55038         return map$$1.zoom() >= context.minEditableZoom();
55039     };
55040
55041
55042     map$$1.minzoom = function(_) {
55043         if (!arguments.length) return minzoom;
55044         minzoom = _;
55045         return map$$1;
55046     };
55047
55048
55049     map$$1.layers = drawLayers;
55050
55051
55052     return utilRebind(map$$1, dispatch$$1, 'on');
55053 }
55054
55055 var TAU = 2 * Math.PI;
55056 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
55057 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
55058 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
55059 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
55060
55061
55062 function uiMapInMap(context) {
55063     var key = '/';
55064
55065
55066     function map_in_map(selection$$1) {
55067         var backgroundLayer = rendererTileLayer(context),
55068             overlayLayers = {},
55069             projection = geoRawMercator(),
55070             gpxLayer = svgGpx(projection, context).showLabels(false),
55071             debugLayer = svgDebug(projection, context),
55072             zoom$$1 = zoom$1()
55073                 .scaleExtent([ztok(0.5), ztok(24)])
55074                 .on('start', zoomStarted)
55075                 .on('zoom', zoomed)
55076                 .on('end', zoomEnded),
55077             isTransformed = false,
55078             isHidden = true,
55079             skipEvents = false,
55080             gesture = null,
55081             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
55082             wrap = select(null),
55083             tiles = select(null),
55084             viewport = select(null),
55085             tStart,  // transform at start of gesture
55086             tCurr,   // transform at most recent event
55087             timeoutId;
55088
55089
55090         function zoomStarted() {
55091             if (skipEvents) return;
55092             tStart = tCurr = projection.transform();
55093             gesture = null;
55094         }
55095
55096
55097         function zoomed() {
55098             if (skipEvents) return;
55099
55100             var x = event.transform.x,
55101                 y = event.transform.y,
55102                 k = event.transform.k,
55103                 isZooming = (k !== tStart.k),
55104                 isPanning = (x !== tStart.x || y !== tStart.y);
55105
55106             if (!isZooming && !isPanning) {
55107                 return;  // no change
55108             }
55109
55110             // lock in either zooming or panning, don't allow both in minimap.
55111             if (!gesture) {
55112                 gesture = isZooming ? 'zoom' : 'pan';
55113             }
55114
55115             var tMini = projection.transform(),
55116                 tX, tY, scale;
55117
55118             if (gesture === 'zoom') {
55119                 var dMini = utilGetDimensions(wrap),
55120                     cMini = vecScale(dMini, 0.5);
55121                 scale = k / tMini.k;
55122                 tX = (cMini[0] / scale - cMini[0]) * scale;
55123                 tY = (cMini[1] / scale - cMini[1]) * scale;
55124             } else {
55125                 k = tMini.k;
55126                 scale = 1;
55127                 tX = x - tMini.x;
55128                 tY = y - tMini.y;
55129             }
55130
55131             utilSetTransform(tiles, tX, tY, scale);
55132             utilSetTransform(viewport, 0, 0, scale);
55133             isTransformed = true;
55134             tCurr = identity$9.translate(x, y).scale(k);
55135
55136             var zMain = ktoz(context.projection.scale()),
55137                 zMini = ktoz(k);
55138
55139             zDiff = zMain - zMini;
55140
55141             queueRedraw();
55142         }
55143
55144
55145         function zoomEnded() {
55146             if (skipEvents) return;
55147             if (gesture !== 'pan') return;
55148
55149             updateProjection();
55150             gesture = null;
55151             var dMini = utilGetDimensions(wrap),
55152                 cMini = vecScale(dMini, 0.5);
55153             context.map().center(projection.invert(cMini));   // recenter main map..
55154         }
55155
55156
55157         function updateProjection() {
55158             var loc = context.map().center(),
55159                 dMini = utilGetDimensions(wrap),
55160                 cMini = vecScale(dMini, 0.5),
55161                 tMain = context.projection.transform(),
55162                 zMain = ktoz(tMain.k),
55163                 zMini = Math.max(zMain - zDiff, 0.5),
55164                 kMini = ztok(zMini);
55165
55166             projection
55167                 .translate([tMain.x, tMain.y])
55168                 .scale(kMini);
55169
55170             var point = projection(loc),
55171                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
55172                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
55173                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
55174
55175             projection
55176                 .translate([xMini, yMini])
55177                 .clipExtent([[0, 0], dMini]);
55178
55179             tCurr = projection.transform();
55180
55181             if (isTransformed) {
55182                 utilSetTransform(tiles, 0, 0);
55183                 utilSetTransform(viewport, 0, 0);
55184                 isTransformed = false;
55185             }
55186
55187             zoom$$1
55188                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
55189
55190             skipEvents = true;
55191             wrap.call(zoom$$1.transform, tCurr);
55192             skipEvents = false;
55193         }
55194
55195
55196         function redraw() {
55197             clearTimeout(timeoutId);
55198             if (isHidden) return;
55199
55200             updateProjection();
55201
55202             var dMini = utilGetDimensions(wrap),
55203                 zMini = ktoz(projection.scale());
55204
55205             // setup tile container
55206             tiles = wrap
55207                 .selectAll('.map-in-map-tiles')
55208                 .data([0]);
55209
55210             tiles = tiles.enter()
55211                 .append('div')
55212                 .attr('class', 'map-in-map-tiles')
55213                 .merge(tiles);
55214
55215             // redraw background
55216             backgroundLayer
55217                 .source(context.background().baseLayerSource())
55218                 .projection(projection)
55219                 .dimensions(dMini);
55220
55221             var background = tiles
55222                 .selectAll('.map-in-map-background')
55223                 .data([0]);
55224
55225             background.enter()
55226                 .append('div')
55227                 .attr('class', 'map-in-map-background')
55228                 .merge(background)
55229                 .call(backgroundLayer);
55230
55231
55232             // redraw overlay
55233             var overlaySources = context.background().overlayLayerSources();
55234             var activeOverlayLayers = [];
55235             for (var i = 0; i < overlaySources.length; i++) {
55236                 if (overlaySources[i].validZoom(zMini)) {
55237                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
55238                     activeOverlayLayers.push(overlayLayers[i]
55239                         .source(overlaySources[i])
55240                         .projection(projection)
55241                         .dimensions(dMini));
55242                 }
55243             }
55244
55245             var overlay = tiles
55246                 .selectAll('.map-in-map-overlay')
55247                 .data([0]);
55248
55249             overlay = overlay.enter()
55250                 .append('div')
55251                 .attr('class', 'map-in-map-overlay')
55252                 .merge(overlay);
55253
55254
55255             var overlays = overlay
55256                 .selectAll('div')
55257                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
55258
55259             overlays.exit()
55260                 .remove();
55261
55262             overlays = overlays.enter()
55263                 .append('div')
55264                 .merge(overlays)
55265                 .each(function(layer) { select(this).call(layer); });
55266
55267
55268             var dataLayers = tiles
55269                 .selectAll('.map-in-map-data')
55270                 .data([0]);
55271
55272             dataLayers.exit()
55273                 .remove();
55274
55275             dataLayers = dataLayers.enter()
55276                 .append('svg')
55277                 .attr('class', 'map-in-map-data')
55278                 .merge(dataLayers)
55279                 .call(gpxLayer)
55280                 .call(debugLayer);
55281
55282
55283             // redraw viewport bounding box
55284             if (gesture !== 'pan') {
55285                 var getPath = index$4(projection),
55286                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
55287
55288                 viewport = wrap.selectAll('.map-in-map-viewport')
55289                     .data([0]);
55290
55291                 viewport = viewport.enter()
55292                     .append('svg')
55293                     .attr('class', 'map-in-map-viewport')
55294                     .merge(viewport);
55295
55296
55297                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
55298                     .data([bbox]);
55299
55300                 path$$1.enter()
55301                     .append('path')
55302                     .attr('class', 'map-in-map-bbox')
55303                     .merge(path$$1)
55304                     .attr('d', getPath)
55305                     .classed('thick', function(d) { return getPath.area(d) < 30; });
55306             }
55307         }
55308
55309
55310         function queueRedraw() {
55311             clearTimeout(timeoutId);
55312             timeoutId = setTimeout(function() { redraw(); }, 750);
55313         }
55314
55315
55316         function toggle() {
55317             if (event) event.preventDefault();
55318
55319             isHidden = !isHidden;
55320
55321             var label = select('.minimap-toggle');
55322             label.classed('active', !isHidden)
55323                 .select('input').property('checked', !isHidden);
55324
55325             if (isHidden) {
55326                 wrap
55327                     .style('display', 'block')
55328                     .style('opacity', '1')
55329                     .transition()
55330                     .duration(200)
55331                     .style('opacity', '0')
55332                     .on('end', function() {
55333                         selection$$1.selectAll('.map-in-map')
55334                             .style('display', 'none');
55335                     });
55336             } else {
55337                 wrap
55338                     .style('display', 'block')
55339                     .style('opacity', '0')
55340                     .transition()
55341                     .duration(200)
55342                     .style('opacity', '1')
55343                     .on('end', function() {
55344                         redraw();
55345                     });
55346             }
55347         }
55348
55349
55350         uiMapInMap.toggle = toggle;
55351
55352         wrap = selection$$1.selectAll('.map-in-map')
55353             .data([0]);
55354
55355         wrap = wrap.enter()
55356             .append('div')
55357             .attr('class', 'map-in-map')
55358             .style('display', (isHidden ? 'none' : 'block'))
55359             .call(zoom$$1)
55360             .on('dblclick.zoom', null)
55361             .merge(wrap);
55362
55363         context.map()
55364             .on('drawn.map-in-map', function(drawn) {
55365                 if (drawn.full === true) {
55366                     redraw();
55367                 }
55368             });
55369
55370         redraw();
55371
55372         var keybinding = d3keybinding('map-in-map')
55373             .on(key, toggle);
55374
55375         select(document)
55376             .call(keybinding);
55377     }
55378
55379     return map_in_map;
55380 }
55381
55382 function uiTooltipHtml(text, key) {
55383     var s = '<span>' + text + '</span>';
55384     if (key) {
55385         s += '<div class="keyhint-wrap">' +
55386             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
55387             '<span class="keyhint"> ' + key + '</span></div>';
55388     }
55389     return s;
55390 }
55391
55392 function uiBackground(context) {
55393     var key = 'B',
55394         detected = utilDetect(),
55395         opacities = [1, 0.75, 0.5, 0.25],
55396         directions = [
55397             ['right', [0.5, 0]],
55398             ['top', [0, -0.5]],
55399             ['left', [-0.5, 0]],
55400             ['bottom', [0, 0.5]]],
55401         opacityDefault = (context.storage('background-opacity') !== null) ?
55402             (+context.storage('background-opacity')) : 1.0,
55403         customTemplate = context.storage('background-custom-template') || '',
55404         previous;
55405
55406     // Can be 0 from <1.3.0 use or due to issue #1923.
55407     if (opacityDefault === 0) opacityDefault = 1.0;
55408
55409
55410     function background(selection$$1) {
55411
55412         function sortSources(a, b) {
55413             return a.best() && !b.best() ? -1
55414                 : b.best() && !a.best() ? 1
55415                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
55416         }
55417
55418
55419         function setOpacity(d) {
55420             var bg = context.container().selectAll('.layer-background')
55421                 .transition()
55422                 .style('opacity', d)
55423                 .attr('data-opacity', d);
55424
55425             if (!detected.opera) {
55426                 utilSetTransform(bg, 0, 0);
55427             }
55428
55429             opacityList.selectAll('li')
55430                 .classed('active', function(_) { return _ === d; });
55431
55432             context.storage('background-opacity', d);
55433         }
55434
55435
55436         function setTooltips(selection$$1) {
55437             selection$$1.each(function(d, i, nodes) {
55438                 var item = select(this).select('label'),
55439                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
55440
55441                 if (d === previous) {
55442                     item.call(tooltip()
55443                         .placement(placement)
55444                         .html(true)
55445                         .title(function() {
55446                             var tip = '<div>' + t('background.switch') + '</div>';
55447                             return uiTooltipHtml(tip, uiCmd('⌘B'));
55448                         })
55449                     );
55450                 } else if (d.description) {
55451                     item.call(tooltip()
55452                         .placement(placement)
55453                         .title(d.description)
55454                     );
55455                 } else {
55456                     item.call(tooltip().destroy);
55457                 }
55458             });
55459         }
55460
55461
55462         function selectLayer() {
55463             function active$$1(d) {
55464                 return context.background().showsLayer(d);
55465             }
55466
55467             content.selectAll('.layer, .custom_layer')
55468                 .classed('active', active$$1)
55469                 .classed('switch', function(d) { return d === previous; })
55470                 .call(setTooltips)
55471                 .selectAll('input')
55472                 .property('checked', active$$1);
55473         }
55474
55475
55476         function clickSetSource(d) {
55477             event.preventDefault();
55478             previous = context.background().baseLayerSource();
55479             context.background().baseLayerSource(d);
55480             selectLayer();
55481             document.activeElement.blur();
55482         }
55483
55484
55485         function editCustom() {
55486             event.preventDefault();
55487             var template = window.prompt(t('background.custom_prompt'), customTemplate);
55488             if (template) {
55489                 setCustom(template);
55490             } else {
55491                 selectLayer();
55492             }
55493         }
55494
55495
55496         function setCustom(template) {
55497             context.storage('background-custom-template', template);
55498             var d = rendererBackgroundSource.Custom(template);
55499             content.selectAll('.custom_layer').datum(d);
55500             clickSetSource(d);
55501         }
55502
55503
55504         function clickSetOverlay(d) {
55505             event.preventDefault();
55506             context.background().toggleOverlayLayer(d);
55507             selectLayer();
55508             document.activeElement.blur();
55509         }
55510
55511
55512         function drawList(layerList, type, change, filter) {
55513             var sources = context.background()
55514                 .sources(context.map().extent())
55515                 .filter(filter);
55516
55517             var layerLinks = layerList.selectAll('li.layer')
55518                 .data(sources, function(d) { return d.name(); });
55519
55520             layerLinks.exit()
55521                 .remove();
55522
55523             var enter = layerLinks.enter()
55524                 .insert('li', '.custom_layer')
55525                 .attr('class', 'layer')
55526                 .classed('best', function(d) { return d.best(); });
55527
55528             enter.filter(function(d) { return d.best(); })
55529                 .append('div')
55530                 .attr('class', 'best')
55531                 .call(tooltip()
55532                     .title(t('background.best_imagery'))
55533                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
55534                 .append('span')
55535                 .html('&#9733;');
55536
55537             var label = enter
55538                 .append('label');
55539
55540             label
55541                 .append('input')
55542                 .attr('type', type)
55543                 .attr('name', 'layers')
55544                 .on('change', change);
55545
55546             label
55547                 .append('span')
55548                 .text(function(d) { return d.name(); });
55549
55550
55551             layerList.selectAll('li.layer')
55552                 .sort(sortSources)
55553                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
55554         }
55555
55556
55557         function update() {
55558             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
55559             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
55560
55561             selectLayer();
55562
55563             var source = context.background().baseLayerSource();
55564             if (source.id === 'custom') {
55565                 customTemplate = source.template;
55566             }
55567
55568             updateOffsetVal();
55569         }
55570
55571
55572         function updateOffsetVal() {
55573             var meters = geoOffsetToMeters(context.background().offset()),
55574                 x = +meters[0].toFixed(2),
55575                 y = +meters[1].toFixed(2);
55576
55577             selectAll('.nudge-inner-rect')
55578                 .select('input')
55579                 .classed('error', false)
55580                 .property('value', x + ', ' + y);
55581
55582             selectAll('.nudge-reset')
55583                 .classed('disabled', function() {
55584                     return (x === 0 && y === 0);
55585                 });
55586         }
55587
55588
55589         function resetOffset() {
55590             if (event.button !== 0) return;
55591             context.background().offset([0, 0]);
55592             updateOffsetVal();
55593         }
55594
55595
55596         function nudge(d) {
55597             context.background().nudge(d, context.map().zoom());
55598             updateOffsetVal();
55599         }
55600
55601
55602         function buttonOffset(d) {
55603             if (event.button !== 0) return;
55604             var timeout$$1 = window.setTimeout(function() {
55605                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
55606                 }, 500),
55607                 interval$$1;
55608
55609             function doneNudge() {
55610                 window.clearTimeout(timeout$$1);
55611                 window.clearInterval(interval$$1);
55612                 select(window)
55613                     .on('mouseup.buttonoffset', null, true)
55614                     .on('mousedown.buttonoffset', null, true);
55615             }
55616
55617             select(window)
55618                 .on('mouseup.buttonoffset', doneNudge, true)
55619                 .on('mousedown.buttonoffset', doneNudge, true);
55620
55621             nudge(d);
55622         }
55623
55624
55625         function inputOffset() {
55626             if (event.button !== 0) return;
55627             var input = select(this);
55628             var d = input.node().value;
55629
55630             if (d === '') return resetOffset();
55631
55632             d = d.replace(/;/g, ',').split(',').map(function(n) {
55633                 // if n is NaN, it will always get mapped to false.
55634                 return !isNaN(n) && n;
55635             });
55636
55637             if (d.length !== 2 || !d[0] || !d[1]) {
55638                 input.classed('error', true);
55639                 return;
55640             }
55641
55642             context.background().offset(geoMetersToOffset(d));
55643             updateOffsetVal();
55644         }
55645
55646
55647         function dragOffset() {
55648             if (event.button !== 0) return;
55649             var origin = [event.clientX, event.clientY];
55650
55651             context.container()
55652                 .append('div')
55653                 .attr('class', 'nudge-surface');
55654
55655             select(window)
55656                 .on('mousemove.offset', function() {
55657                     var latest = [event.clientX, event.clientY];
55658                     var d = [
55659                         -(origin[0] - latest[0]) / 4,
55660                         -(origin[1] - latest[1]) / 4
55661                     ];
55662
55663                     origin = latest;
55664                     nudge(d);
55665                 })
55666                 .on('mouseup.offset', function() {
55667                     if (event.button !== 0) return;
55668                     selectAll('.nudge-surface')
55669                         .remove();
55670
55671                     select(window)
55672                         .on('mousemove.offset', null)
55673                         .on('mouseup.offset', null);
55674                 });
55675
55676             event.preventDefault();
55677         }
55678
55679
55680         function hide() {
55681             setVisible(false);
55682         }
55683
55684
55685         function toggle() {
55686             if (event) event.preventDefault();
55687             tooltipBehavior.hide(button);
55688             setVisible(!button.classed('active'));
55689         }
55690
55691
55692         function quickSwitch() {
55693             if (previous) {
55694                 clickSetSource(previous);
55695             }
55696         }
55697
55698
55699         function setVisible(show) {
55700             if (show !== shown) {
55701                 button.classed('active', show);
55702                 shown = show;
55703
55704                 if (show) {
55705                     selection$$1.on('mousedown.background-inside', function() {
55706                         event.stopPropagation();
55707                     });
55708                     content
55709                         .style('display', 'block')
55710                         .style('right', '-300px')
55711                         .transition()
55712                         .duration(200)
55713                         .style('right', '0px');
55714                 } else {
55715                     content
55716                         .style('display', 'block')
55717                         .style('right', '0px')
55718                         .transition()
55719                         .duration(200)
55720                         .style('right', '-300px')
55721                         .on('end', function() {
55722                             select(this).style('display', 'none');
55723                         });
55724                     selection$$1.on('mousedown.background-inside', null);
55725                 }
55726             }
55727         }
55728
55729
55730         var content = selection$$1
55731                 .append('div')
55732                 .attr('class', 'fillL map-overlay col3 content hide'),
55733             tooltipBehavior = tooltip()
55734                 .placement((textDirection === 'rtl') ? 'right' : 'left')
55735                 .html(true)
55736                 .title(uiTooltipHtml(t('background.description'), key)),
55737             button = selection$$1
55738                 .append('button')
55739                 .attr('tabindex', -1)
55740                 .on('click', toggle)
55741                 .call(svgIcon('#icon-layers', 'light'))
55742                 .call(tooltipBehavior),
55743             shown = false;
55744
55745
55746         /* opacity switcher */
55747
55748         var opawrap = content
55749                 .append('div')
55750                 .attr('class', 'opacity-options-wrapper');
55751
55752         opawrap
55753             .append('h4')
55754             .text(t('background.title'));
55755
55756         var opacityList = opawrap
55757             .append('ul')
55758             .attr('class', 'opacity-options');
55759
55760         opacityList.selectAll('div.opacity')
55761             .data(opacities)
55762             .enter()
55763             .append('li')
55764             .attr('data-original-title', function(d) {
55765                 return t('background.percent_brightness', { opacity: (d * 100) });
55766             })
55767             .on('click.set-opacity', setOpacity)
55768             .html('<div class="select-box"></div>')
55769             .call(tooltip()
55770                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55771             .append('div')
55772             .attr('class', 'opacity')
55773             .style('opacity', function(d) { return 1.25 - d; });
55774
55775
55776         /* background switcher */
55777
55778         var backgroundList = content
55779             .append('ul')
55780             .attr('class', 'layer-list')
55781             .attr('dir', 'auto');
55782
55783         var custom = backgroundList
55784             .append('li')
55785             .attr('class', 'custom_layer')
55786             .datum(rendererBackgroundSource.Custom());
55787
55788         custom
55789             .append('button')
55790             .attr('class', 'layer-browse')
55791             .call(tooltip()
55792                 .title(t('background.custom_button'))
55793                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55794             .on('click', editCustom)
55795             .call(svgIcon('#icon-search'));
55796
55797         var label = custom
55798             .append('label');
55799
55800         label
55801             .append('input')
55802             .attr('type', 'radio')
55803             .attr('name', 'layers')
55804             .on('change', function () {
55805                 if (customTemplate) {
55806                     setCustom(customTemplate);
55807                 } else {
55808                     editCustom();
55809                 }
55810             });
55811
55812         label
55813             .append('span')
55814             .text(t('background.custom'));
55815
55816         content
55817             .append('div')
55818             .attr('class', 'imagery-faq')
55819             .append('a')
55820             .attr('target', '_blank')
55821             .attr('tabindex', -1)
55822             .call(svgIcon('#icon-out-link', 'inline'))
55823             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
55824             .append('span')
55825             .text(t('background.imagery_source_faq'));
55826
55827         var overlayList = content
55828             .append('ul')
55829             .attr('class', 'layer-list');
55830
55831         var controls = content
55832             .append('div')
55833             .attr('class', 'controls-list');
55834
55835
55836         /* minimap toggle */
55837
55838         var minimapLabel = controls
55839             .append('label')
55840             .call(tooltip()
55841                 .html(true)
55842                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
55843                 .placement('top')
55844             );
55845
55846         minimapLabel
55847             .classed('minimap-toggle', true)
55848             .append('input')
55849             .attr('type', 'checkbox')
55850             .on('change', function() {
55851                 uiMapInMap.toggle();
55852                 event.preventDefault();
55853             });
55854
55855         minimapLabel
55856             .append('span')
55857             .text(t('background.minimap.description'));
55858
55859
55860         /* imagery offset controls */
55861
55862         var adjustments = content
55863             .append('div')
55864             .attr('class', 'adjustments');
55865
55866         adjustments
55867             .append('a')
55868             .text(t('background.fix_misalignment'))
55869             .attr('href', '#')
55870             .classed('hide-toggle', true)
55871             .classed('expanded', false)
55872             .on('click', function() {
55873                 if (event.button !== 0) return;
55874                 var exp = select(this).classed('expanded');
55875                 nudgeContainer.style('display', exp ? 'none' : 'block');
55876                 select(this).classed('expanded', !exp);
55877                 event.preventDefault();
55878             });
55879
55880         var nudgeContainer = adjustments
55881             .append('div')
55882             .attr('class', 'nudge-container cf')
55883             .style('display', 'none');
55884
55885         nudgeContainer
55886             .append('div')
55887             .attr('class', 'nudge-instructions')
55888             .text(t('background.offset'));
55889
55890         var nudgeRect = nudgeContainer
55891             .append('div')
55892             .attr('class', 'nudge-outer-rect')
55893             .on('mousedown', dragOffset);
55894
55895         nudgeRect
55896             .append('div')
55897             .attr('class', 'nudge-inner-rect')
55898             .append('input')
55899             .on('change', inputOffset)
55900             .on('mousedown', function() {
55901                 if (event.button !== 0) return;
55902                 event.stopPropagation();
55903             });
55904
55905         nudgeContainer
55906             .append('div')
55907             .selectAll('button')
55908             .data(directions).enter()
55909             .append('button')
55910             .attr('class', function(d) { return d[0] + ' nudge'; })
55911             .on('mousedown', function(d) {
55912                 if (event.button !== 0) return;
55913                 buttonOffset(d[1]);
55914             });
55915
55916         nudgeContainer
55917             .append('button')
55918             .attr('title', t('background.reset'))
55919             .attr('class', 'nudge-reset disabled')
55920             .on('click', resetOffset)
55921             .call(
55922                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
55923             );
55924
55925         context.map()
55926             .on('move.background-update', lodash.debounce(update, 1000));
55927
55928         context.background()
55929             .on('change.background-update', update);
55930
55931
55932         update();
55933         setOpacity(opacityDefault);
55934
55935         var keybinding = d3keybinding('background')
55936             .on(key, toggle)
55937             .on(uiCmd('⌘B'), quickSwitch)
55938             .on('F', hide)
55939             .on('H', hide);
55940
55941         select(document)
55942             .call(keybinding);
55943
55944         context.surface().on('mousedown.background-outside', hide);
55945         context.container().on('mousedown.background-outside', hide);
55946     }
55947
55948     return background;
55949 }
55950
55951 function uiContributors(context) {
55952     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
55953         limit = 4,
55954         hidden = false,
55955         wrap = select(null);
55956
55957
55958     function update() {
55959         var users = {},
55960             entities = context.intersects(context.map().extent());
55961
55962         entities.forEach(function(entity) {
55963             if (entity && entity.user) users[entity.user] = true;
55964         });
55965
55966         var u = Object.keys(users),
55967             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
55968
55969         wrap.html('')
55970             .call(svgIcon('#icon-nearby', 'pre-text light'));
55971
55972         var userList = select(document.createElement('span'));
55973
55974         userList.selectAll()
55975             .data(subset)
55976             .enter()
55977             .append('a')
55978             .attr('class', 'user-link')
55979             .attr('href', function(d) { return context.connection().userURL(d); })
55980             .attr('target', '_blank')
55981             .attr('tabindex', -1)
55982             .text(String);
55983
55984         if (u.length > limit) {
55985             var count = select(document.createElement('span'));
55986
55987             count.append('a')
55988                 .attr('target', '_blank')
55989                 .attr('tabindex', -1)
55990                 .attr('href', function() {
55991                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
55992                 })
55993                 .text(u.length - limit + 1);
55994
55995             wrap.append('span')
55996                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
55997
55998         } else {
55999             wrap.append('span')
56000                 .html(t('contributors.list', { users: userList.html() }));
56001         }
56002
56003         if (!u.length) {
56004             hidden = true;
56005             wrap
56006                 .transition()
56007                 .style('opacity', 0);
56008
56009         } else if (hidden) {
56010             wrap
56011                 .transition()
56012                 .style('opacity', 1);
56013         }
56014     }
56015
56016
56017     return function(selection$$1) {
56018         wrap = selection$$1;
56019         update();
56020
56021         context.connection().on('loaded.contributors', debouncedUpdate);
56022         context.map().on('move.contributors', debouncedUpdate);
56023     };
56024 }
56025
56026 function uiFeatureInfo(context) {
56027     function update(selection$$1) {
56028         var features = context.features(),
56029             stats = features.stats(),
56030             count = 0,
56031             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
56032                 if (stats[k]) {
56033                     count += stats[k];
56034                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
56035                 }
56036             }));
56037
56038         selection$$1.html('');
56039
56040         if (hiddenList.length) {
56041             var tooltipBehavior = tooltip()
56042                     .placement('top')
56043                     .html(true)
56044                     .title(function() {
56045                         return uiTooltipHtml(hiddenList.join('<br/>'));
56046                     });
56047
56048             var warning = selection$$1.append('a')
56049                 .attr('href', '#')
56050                 .attr('tabindex', -1)
56051                 .html(t('feature_info.hidden_warning', { count: count }))
56052                 .call(tooltipBehavior)
56053                 .on('click', function() {
56054                     tooltipBehavior.hide(warning);
56055                     // open map data panel?
56056                     event.preventDefault();
56057                 });
56058         }
56059
56060         selection$$1
56061             .classed('hide', !hiddenList.length);
56062     }
56063
56064
56065     return function(selection$$1) {
56066         update(selection$$1);
56067
56068         context.features().on('change.feature_info', function() {
56069             update(selection$$1);
56070         });
56071     };
56072 }
56073
56074 function uiFullScreen(context) {
56075     var element = context.container().node(),
56076         keybinding = d3keybinding('full-screen');
56077         // button;
56078
56079
56080     function getFullScreenFn() {
56081         if (element.requestFullscreen) {
56082             return element.requestFullscreen;
56083         } else if (element.msRequestFullscreen) {
56084             return element.msRequestFullscreen;
56085         } else if (element.mozRequestFullScreen) {
56086             return element.mozRequestFullScreen;
56087         } else if (element.webkitRequestFullscreen) {
56088             return element.webkitRequestFullscreen;
56089         }
56090     }
56091
56092
56093     function getExitFullScreenFn() {
56094         if (document.exitFullscreen) {
56095             return document.exitFullscreen;
56096         } else if (document.msExitFullscreen) {
56097             return document.msExitFullscreen;
56098         } else if (document.mozCancelFullScreen) {
56099             return document.mozCancelFullScreen;
56100         } else if (document.webkitExitFullscreen) {
56101             return document.webkitExitFullscreen;
56102         }
56103     }
56104
56105
56106     function isFullScreen() {
56107         return document.fullscreenElement ||
56108             document.mozFullScreenElement ||
56109             document.webkitFullscreenElement ||
56110             document.msFullscreenElement;
56111     }
56112
56113
56114     function isSupported() {
56115         return !!getFullScreenFn();
56116     }
56117
56118
56119     function fullScreen() {
56120         event.preventDefault();
56121         if (!isFullScreen()) {
56122             // button.classed('active', true);
56123             getFullScreenFn().apply(element);
56124         } else {
56125             // button.classed('active', false);
56126             getExitFullScreenFn().apply(document);
56127         }
56128     }
56129
56130
56131     return function() { // selection) {
56132         if (!isSupported())
56133             return;
56134
56135         // button = selection.append('button')
56136         //     .attr('title', t('full_screen'))
56137         //     .attr('tabindex', -1)
56138         //     .on('click', fullScreen)
56139         //     .call(tooltip);
56140
56141         // button.append('span')
56142         //     .attr('class', 'icon full-screen');
56143
56144         keybinding
56145             .on('f11', fullScreen)
56146             .on(uiCmd('⌘⇧F'), fullScreen);
56147
56148         select(document)
56149             .call(keybinding);
56150     };
56151 }
56152
56153 function uiModal(selection$$1, blocking) {
56154     var keybinding = d3keybinding('modal');
56155     var previous = selection$$1.select('div.modal');
56156     var animate = previous.empty();
56157
56158     previous.transition()
56159         .duration(200)
56160         .style('opacity', 0)
56161         .remove();
56162
56163     var shaded = selection$$1
56164         .append('div')
56165         .attr('class', 'shaded')
56166         .style('opacity', 0);
56167
56168     shaded.close = function() {
56169         shaded
56170             .transition()
56171             .duration(200)
56172             .style('opacity',0)
56173             .remove();
56174
56175         modal
56176             .transition()
56177             .duration(200)
56178             .style('top','0px');
56179
56180         keybinding.off();
56181     };
56182
56183
56184     var modal = shaded
56185         .append('div')
56186         .attr('class', 'modal fillL col6');
56187
56188     if (!blocking) {
56189         shaded.on('click.remove-modal', function() {
56190             if (event.target === this) {
56191                 shaded.close();
56192             }
56193         });
56194
56195         modal.append('button')
56196             .attr('class', 'close')
56197             .on('click', shaded.close)
56198             .call(svgIcon('#icon-close'));
56199
56200         keybinding
56201             .on('⌫', shaded.close)
56202             .on('⎋', shaded.close);
56203
56204         select(document)
56205             .call(keybinding);
56206     }
56207
56208     modal
56209         .append('div')
56210         .attr('class', 'content');
56211
56212     if (animate) {
56213         shaded.transition().style('opacity', 1);
56214     } else {
56215         shaded.style('opacity', 1);
56216     }
56217
56218
56219     return shaded;
56220 }
56221
56222 function uiLoading(context) {
56223     var message = '',
56224         blocking = false,
56225         modalSelection;
56226
56227
56228     var loading = function(selection) {
56229         modalSelection = uiModal(selection, blocking);
56230
56231         var loadertext = modalSelection.select('.content')
56232             .classed('loading-modal', true)
56233             .append('div')
56234             .attr('class', 'modal-section fillL');
56235
56236         loadertext
56237             .append('img')
56238             .attr('class', 'loader')
56239             .attr('src', context.imagePath('loader-white.gif'));
56240
56241         loadertext
56242             .append('h3')
56243             .text(message);
56244
56245         modalSelection.select('button.close')
56246             .attr('class', 'hide');
56247
56248         return loading;
56249     };
56250
56251
56252     loading.message = function(_) {
56253         if (!arguments.length) return message;
56254         message = _;
56255         return loading;
56256     };
56257
56258
56259     loading.blocking = function(_) {
56260         if (!arguments.length) return blocking;
56261         blocking = _;
56262         return loading;
56263     };
56264
56265
56266     loading.close = function() {
56267         modalSelection.remove();
56268     };
56269
56270
56271     return loading;
56272 }
56273
56274 function uiGeolocate(context) {
56275     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
56276         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
56277         timeoutId;
56278
56279
56280     function click() {
56281         context.enter(modeBrowse(context));
56282         context.container().call(locating);
56283         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
56284
56285         // This timeout ensures that we still call finish() even if
56286         // the user declines to share their location in Firefox
56287         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
56288     }
56289
56290
56291     function success(position) {
56292         var map = context.map(),
56293             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
56294                 .padByMeters(position.coords.accuracy);
56295
56296         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
56297         finish();
56298     }
56299
56300
56301     function error() {
56302         finish();
56303     }
56304
56305
56306     function finish() {
56307         locating.close();  // unblock ui
56308         if (timeoutId) { clearTimeout(timeoutId); }
56309         timeoutId = undefined;
56310     }
56311
56312
56313     return function(selection) {
56314         if (!navigator.geolocation) return;
56315
56316         selection
56317             .append('button')
56318             .attr('tabindex', -1)
56319             .attr('title', t('geolocate.title'))
56320             .on('click', click)
56321             .call(svgIcon('#icon-geolocate', 'light'))
56322             .call(tooltip()
56323                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
56324     };
56325 }
56326
56327 var marked = createCommonjsModule(function (module, exports) {
56328 /**
56329  * marked - a markdown parser
56330  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
56331  * https://github.com/chjj/marked
56332  */
56333
56334 (function() {
56335
56336 /**
56337  * Block-Level Grammar
56338  */
56339
56340 var block = {
56341   newline: /^\n+/,
56342   code: /^( {4}[^\n]+\n*)+/,
56343   fences: noop,
56344   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
56345   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
56346   nptable: noop,
56347   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
56348   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
56349   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
56350   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
56351   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
56352   table: noop,
56353   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
56354   text: /^[^\n]+/
56355 };
56356
56357 block.bullet = /(?:[*+-]|\d+\.)/;
56358 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
56359 block.item = replace(block.item, 'gm')
56360   (/bull/g, block.bullet)
56361   ();
56362
56363 block.list = replace(block.list)
56364   (/bull/g, block.bullet)
56365   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
56366   ('def', '\\n+(?=' + block.def.source + ')')
56367   ();
56368
56369 block.blockquote = replace(block.blockquote)
56370   ('def', block.def)
56371   ();
56372
56373 block._tag = '(?!(?:'
56374   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
56375   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
56376   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
56377
56378 block.html = replace(block.html)
56379   ('comment', /<!--[\s\S]*?-->/)
56380   ('closed', /<(tag)[\s\S]+?<\/\1>/)
56381   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
56382   (/tag/g, block._tag)
56383   ();
56384
56385 block.paragraph = replace(block.paragraph)
56386   ('hr', block.hr)
56387   ('heading', block.heading)
56388   ('lheading', block.lheading)
56389   ('blockquote', block.blockquote)
56390   ('tag', '<' + block._tag)
56391   ('def', block.def)
56392   ();
56393
56394 /**
56395  * Normal Block Grammar
56396  */
56397
56398 block.normal = merge({}, block);
56399
56400 /**
56401  * GFM Block Grammar
56402  */
56403
56404 block.gfm = merge({}, block.normal, {
56405   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
56406   paragraph: /^/,
56407   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
56408 });
56409
56410 block.gfm.paragraph = replace(block.paragraph)
56411   ('(?!', '(?!'
56412     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
56413     + block.list.source.replace('\\1', '\\3') + '|')
56414   ();
56415
56416 /**
56417  * GFM + Tables Block Grammar
56418  */
56419
56420 block.tables = merge({}, block.gfm, {
56421   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
56422   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
56423 });
56424
56425 /**
56426  * Block Lexer
56427  */
56428
56429 function Lexer(options) {
56430   this.tokens = [];
56431   this.tokens.links = {};
56432   this.options = options || marked.defaults;
56433   this.rules = block.normal;
56434
56435   if (this.options.gfm) {
56436     if (this.options.tables) {
56437       this.rules = block.tables;
56438     } else {
56439       this.rules = block.gfm;
56440     }
56441   }
56442 }
56443
56444 /**
56445  * Expose Block Rules
56446  */
56447
56448 Lexer.rules = block;
56449
56450 /**
56451  * Static Lex Method
56452  */
56453
56454 Lexer.lex = function(src, options) {
56455   var lexer = new Lexer(options);
56456   return lexer.lex(src);
56457 };
56458
56459 /**
56460  * Preprocessing
56461  */
56462
56463 Lexer.prototype.lex = function(src) {
56464   src = src
56465     .replace(/\r\n|\r/g, '\n')
56466     .replace(/\t/g, '    ')
56467     .replace(/\u00a0/g, ' ')
56468     .replace(/\u2424/g, '\n');
56469
56470   return this.token(src, true);
56471 };
56472
56473 /**
56474  * Lexing
56475  */
56476
56477 Lexer.prototype.token = function(src, top, bq) {
56478   var src = src.replace(/^ +$/gm, '')
56479     , next
56480     , loose
56481     , cap
56482     , bull
56483     , b
56484     , item
56485     , space
56486     , i
56487     , l;
56488
56489   while (src) {
56490     // newline
56491     if (cap = this.rules.newline.exec(src)) {
56492       src = src.substring(cap[0].length);
56493       if (cap[0].length > 1) {
56494         this.tokens.push({
56495           type: 'space'
56496         });
56497       }
56498     }
56499
56500     // code
56501     if (cap = this.rules.code.exec(src)) {
56502       src = src.substring(cap[0].length);
56503       cap = cap[0].replace(/^ {4}/gm, '');
56504       this.tokens.push({
56505         type: 'code',
56506         text: !this.options.pedantic
56507           ? cap.replace(/\n+$/, '')
56508           : cap
56509       });
56510       continue;
56511     }
56512
56513     // fences (gfm)
56514     if (cap = this.rules.fences.exec(src)) {
56515       src = src.substring(cap[0].length);
56516       this.tokens.push({
56517         type: 'code',
56518         lang: cap[2],
56519         text: cap[3] || ''
56520       });
56521       continue;
56522     }
56523
56524     // heading
56525     if (cap = this.rules.heading.exec(src)) {
56526       src = src.substring(cap[0].length);
56527       this.tokens.push({
56528         type: 'heading',
56529         depth: cap[1].length,
56530         text: cap[2]
56531       });
56532       continue;
56533     }
56534
56535     // table no leading pipe (gfm)
56536     if (top && (cap = this.rules.nptable.exec(src))) {
56537       src = src.substring(cap[0].length);
56538
56539       item = {
56540         type: 'table',
56541         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56542         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56543         cells: cap[3].replace(/\n$/, '').split('\n')
56544       };
56545
56546       for (i = 0; i < item.align.length; i++) {
56547         if (/^ *-+: *$/.test(item.align[i])) {
56548           item.align[i] = 'right';
56549         } else if (/^ *:-+: *$/.test(item.align[i])) {
56550           item.align[i] = 'center';
56551         } else if (/^ *:-+ *$/.test(item.align[i])) {
56552           item.align[i] = 'left';
56553         } else {
56554           item.align[i] = null;
56555         }
56556       }
56557
56558       for (i = 0; i < item.cells.length; i++) {
56559         item.cells[i] = item.cells[i].split(/ *\| */);
56560       }
56561
56562       this.tokens.push(item);
56563
56564       continue;
56565     }
56566
56567     // lheading
56568     if (cap = this.rules.lheading.exec(src)) {
56569       src = src.substring(cap[0].length);
56570       this.tokens.push({
56571         type: 'heading',
56572         depth: cap[2] === '=' ? 1 : 2,
56573         text: cap[1]
56574       });
56575       continue;
56576     }
56577
56578     // hr
56579     if (cap = this.rules.hr.exec(src)) {
56580       src = src.substring(cap[0].length);
56581       this.tokens.push({
56582         type: 'hr'
56583       });
56584       continue;
56585     }
56586
56587     // blockquote
56588     if (cap = this.rules.blockquote.exec(src)) {
56589       src = src.substring(cap[0].length);
56590
56591       this.tokens.push({
56592         type: 'blockquote_start'
56593       });
56594
56595       cap = cap[0].replace(/^ *> ?/gm, '');
56596
56597       // Pass `top` to keep the current
56598       // "toplevel" state. This is exactly
56599       // how markdown.pl works.
56600       this.token(cap, top, true);
56601
56602       this.tokens.push({
56603         type: 'blockquote_end'
56604       });
56605
56606       continue;
56607     }
56608
56609     // list
56610     if (cap = this.rules.list.exec(src)) {
56611       src = src.substring(cap[0].length);
56612       bull = cap[2];
56613
56614       this.tokens.push({
56615         type: 'list_start',
56616         ordered: bull.length > 1
56617       });
56618
56619       // Get each top-level item.
56620       cap = cap[0].match(this.rules.item);
56621
56622       next = false;
56623       l = cap.length;
56624       i = 0;
56625
56626       for (; i < l; i++) {
56627         item = cap[i];
56628
56629         // Remove the list item's bullet
56630         // so it is seen as the next token.
56631         space = item.length;
56632         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
56633
56634         // Outdent whatever the
56635         // list item contains. Hacky.
56636         if (~item.indexOf('\n ')) {
56637           space -= item.length;
56638           item = !this.options.pedantic
56639             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
56640             : item.replace(/^ {1,4}/gm, '');
56641         }
56642
56643         // Determine whether the next list item belongs here.
56644         // Backpedal if it does not belong in this list.
56645         if (this.options.smartLists && i !== l - 1) {
56646           b = block.bullet.exec(cap[i + 1])[0];
56647           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
56648             src = cap.slice(i + 1).join('\n') + src;
56649             i = l - 1;
56650           }
56651         }
56652
56653         // Determine whether item is loose or not.
56654         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
56655         // for discount behavior.
56656         loose = next || /\n\n(?!\s*$)/.test(item);
56657         if (i !== l - 1) {
56658           next = item.charAt(item.length - 1) === '\n';
56659           if (!loose) loose = next;
56660         }
56661
56662         this.tokens.push({
56663           type: loose
56664             ? 'loose_item_start'
56665             : 'list_item_start'
56666         });
56667
56668         // Recurse.
56669         this.token(item, false, bq);
56670
56671         this.tokens.push({
56672           type: 'list_item_end'
56673         });
56674       }
56675
56676       this.tokens.push({
56677         type: 'list_end'
56678       });
56679
56680       continue;
56681     }
56682
56683     // html
56684     if (cap = this.rules.html.exec(src)) {
56685       src = src.substring(cap[0].length);
56686       this.tokens.push({
56687         type: this.options.sanitize
56688           ? 'paragraph'
56689           : 'html',
56690         pre: !this.options.sanitizer
56691           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
56692         text: cap[0]
56693       });
56694       continue;
56695     }
56696
56697     // def
56698     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
56699       src = src.substring(cap[0].length);
56700       this.tokens.links[cap[1].toLowerCase()] = {
56701         href: cap[2],
56702         title: cap[3]
56703       };
56704       continue;
56705     }
56706
56707     // table (gfm)
56708     if (top && (cap = this.rules.table.exec(src))) {
56709       src = src.substring(cap[0].length);
56710
56711       item = {
56712         type: 'table',
56713         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56714         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56715         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
56716       };
56717
56718       for (i = 0; i < item.align.length; i++) {
56719         if (/^ *-+: *$/.test(item.align[i])) {
56720           item.align[i] = 'right';
56721         } else if (/^ *:-+: *$/.test(item.align[i])) {
56722           item.align[i] = 'center';
56723         } else if (/^ *:-+ *$/.test(item.align[i])) {
56724           item.align[i] = 'left';
56725         } else {
56726           item.align[i] = null;
56727         }
56728       }
56729
56730       for (i = 0; i < item.cells.length; i++) {
56731         item.cells[i] = item.cells[i]
56732           .replace(/^ *\| *| *\| *$/g, '')
56733           .split(/ *\| */);
56734       }
56735
56736       this.tokens.push(item);
56737
56738       continue;
56739     }
56740
56741     // top-level paragraph
56742     if (top && (cap = this.rules.paragraph.exec(src))) {
56743       src = src.substring(cap[0].length);
56744       this.tokens.push({
56745         type: 'paragraph',
56746         text: cap[1].charAt(cap[1].length - 1) === '\n'
56747           ? cap[1].slice(0, -1)
56748           : cap[1]
56749       });
56750       continue;
56751     }
56752
56753     // text
56754     if (cap = this.rules.text.exec(src)) {
56755       // Top-level should never reach here.
56756       src = src.substring(cap[0].length);
56757       this.tokens.push({
56758         type: 'text',
56759         text: cap[0]
56760       });
56761       continue;
56762     }
56763
56764     if (src) {
56765       throw new
56766         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56767     }
56768   }
56769
56770   return this.tokens;
56771 };
56772
56773 /**
56774  * Inline-Level Grammar
56775  */
56776
56777 var inline = {
56778   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
56779   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
56780   url: noop,
56781   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
56782   link: /^!?\[(inside)\]\(href\)/,
56783   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
56784   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
56785   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
56786   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
56787   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
56788   br: /^ {2,}\n(?!\s*$)/,
56789   del: noop,
56790   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
56791 };
56792
56793 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
56794 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
56795
56796 inline.link = replace(inline.link)
56797   ('inside', inline._inside)
56798   ('href', inline._href)
56799   ();
56800
56801 inline.reflink = replace(inline.reflink)
56802   ('inside', inline._inside)
56803   ();
56804
56805 /**
56806  * Normal Inline Grammar
56807  */
56808
56809 inline.normal = merge({}, inline);
56810
56811 /**
56812  * Pedantic Inline Grammar
56813  */
56814
56815 inline.pedantic = merge({}, inline.normal, {
56816   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
56817   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
56818 });
56819
56820 /**
56821  * GFM Inline Grammar
56822  */
56823
56824 inline.gfm = merge({}, inline.normal, {
56825   escape: replace(inline.escape)('])', '~|])')(),
56826   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
56827   del: /^~~(?=\S)([\s\S]*?\S)~~/,
56828   text: replace(inline.text)
56829     (']|', '~]|')
56830     ('|', '|https?://|')
56831     ()
56832 });
56833
56834 /**
56835  * GFM + Line Breaks Inline Grammar
56836  */
56837
56838 inline.breaks = merge({}, inline.gfm, {
56839   br: replace(inline.br)('{2,}', '*')(),
56840   text: replace(inline.gfm.text)('{2,}', '*')()
56841 });
56842
56843 /**
56844  * Inline Lexer & Compiler
56845  */
56846
56847 function InlineLexer(links, options) {
56848   this.options = options || marked.defaults;
56849   this.links = links;
56850   this.rules = inline.normal;
56851   this.renderer = this.options.renderer || new Renderer;
56852   this.renderer.options = this.options;
56853
56854   if (!this.links) {
56855     throw new
56856       Error('Tokens array requires a `links` property.');
56857   }
56858
56859   if (this.options.gfm) {
56860     if (this.options.breaks) {
56861       this.rules = inline.breaks;
56862     } else {
56863       this.rules = inline.gfm;
56864     }
56865   } else if (this.options.pedantic) {
56866     this.rules = inline.pedantic;
56867   }
56868 }
56869
56870 /**
56871  * Expose Inline Rules
56872  */
56873
56874 InlineLexer.rules = inline;
56875
56876 /**
56877  * Static Lexing/Compiling Method
56878  */
56879
56880 InlineLexer.output = function(src, links, options) {
56881   var inline = new InlineLexer(links, options);
56882   return inline.output(src);
56883 };
56884
56885 /**
56886  * Lexing/Compiling
56887  */
56888
56889 InlineLexer.prototype.output = function(src) {
56890   var out = ''
56891     , link
56892     , text
56893     , href
56894     , cap;
56895
56896   while (src) {
56897     // escape
56898     if (cap = this.rules.escape.exec(src)) {
56899       src = src.substring(cap[0].length);
56900       out += cap[1];
56901       continue;
56902     }
56903
56904     // autolink
56905     if (cap = this.rules.autolink.exec(src)) {
56906       src = src.substring(cap[0].length);
56907       if (cap[2] === '@') {
56908         text = cap[1].charAt(6) === ':'
56909           ? this.mangle(cap[1].substring(7))
56910           : this.mangle(cap[1]);
56911         href = this.mangle('mailto:') + text;
56912       } else {
56913         text = escape(cap[1]);
56914         href = text;
56915       }
56916       out += this.renderer.link(href, null, text);
56917       continue;
56918     }
56919
56920     // url (gfm)
56921     if (!this.inLink && (cap = this.rules.url.exec(src))) {
56922       src = src.substring(cap[0].length);
56923       text = escape(cap[1]);
56924       href = text;
56925       out += this.renderer.link(href, null, text);
56926       continue;
56927     }
56928
56929     // tag
56930     if (cap = this.rules.tag.exec(src)) {
56931       if (!this.inLink && /^<a /i.test(cap[0])) {
56932         this.inLink = true;
56933       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
56934         this.inLink = false;
56935       }
56936       src = src.substring(cap[0].length);
56937       out += this.options.sanitize
56938         ? this.options.sanitizer
56939           ? this.options.sanitizer(cap[0])
56940           : escape(cap[0])
56941         : cap[0];
56942       continue;
56943     }
56944
56945     // link
56946     if (cap = this.rules.link.exec(src)) {
56947       src = src.substring(cap[0].length);
56948       this.inLink = true;
56949       out += this.outputLink(cap, {
56950         href: cap[2],
56951         title: cap[3]
56952       });
56953       this.inLink = false;
56954       continue;
56955     }
56956
56957     // reflink, nolink
56958     if ((cap = this.rules.reflink.exec(src))
56959         || (cap = this.rules.nolink.exec(src))) {
56960       src = src.substring(cap[0].length);
56961       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
56962       link = this.links[link.toLowerCase()];
56963       if (!link || !link.href) {
56964         out += cap[0].charAt(0);
56965         src = cap[0].substring(1) + src;
56966         continue;
56967       }
56968       this.inLink = true;
56969       out += this.outputLink(cap, link);
56970       this.inLink = false;
56971       continue;
56972     }
56973
56974     // strong
56975     if (cap = this.rules.strong.exec(src)) {
56976       src = src.substring(cap[0].length);
56977       out += this.renderer.strong(this.output(cap[2] || cap[1]));
56978       continue;
56979     }
56980
56981     // em
56982     if (cap = this.rules.em.exec(src)) {
56983       src = src.substring(cap[0].length);
56984       out += this.renderer.em(this.output(cap[2] || cap[1]));
56985       continue;
56986     }
56987
56988     // code
56989     if (cap = this.rules.code.exec(src)) {
56990       src = src.substring(cap[0].length);
56991       out += this.renderer.codespan(escape(cap[2], true));
56992       continue;
56993     }
56994
56995     // br
56996     if (cap = this.rules.br.exec(src)) {
56997       src = src.substring(cap[0].length);
56998       out += this.renderer.br();
56999       continue;
57000     }
57001
57002     // del (gfm)
57003     if (cap = this.rules.del.exec(src)) {
57004       src = src.substring(cap[0].length);
57005       out += this.renderer.del(this.output(cap[1]));
57006       continue;
57007     }
57008
57009     // text
57010     if (cap = this.rules.text.exec(src)) {
57011       src = src.substring(cap[0].length);
57012       out += this.renderer.text(escape(this.smartypants(cap[0])));
57013       continue;
57014     }
57015
57016     if (src) {
57017       throw new
57018         Error('Infinite loop on byte: ' + src.charCodeAt(0));
57019     }
57020   }
57021
57022   return out;
57023 };
57024
57025 /**
57026  * Compile Link
57027  */
57028
57029 InlineLexer.prototype.outputLink = function(cap, link) {
57030   var href = escape(link.href)
57031     , title = link.title ? escape(link.title) : null;
57032
57033   return cap[0].charAt(0) !== '!'
57034     ? this.renderer.link(href, title, this.output(cap[1]))
57035     : this.renderer.image(href, title, escape(cap[1]));
57036 };
57037
57038 /**
57039  * Smartypants Transformations
57040  */
57041
57042 InlineLexer.prototype.smartypants = function(text) {
57043   if (!this.options.smartypants) return text;
57044   return text
57045     // em-dashes
57046     .replace(/---/g, '\u2014')
57047     // en-dashes
57048     .replace(/--/g, '\u2013')
57049     // opening singles
57050     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
57051     // closing singles & apostrophes
57052     .replace(/'/g, '\u2019')
57053     // opening doubles
57054     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
57055     // closing doubles
57056     .replace(/"/g, '\u201d')
57057     // ellipses
57058     .replace(/\.{3}/g, '\u2026');
57059 };
57060
57061 /**
57062  * Mangle Links
57063  */
57064
57065 InlineLexer.prototype.mangle = function(text) {
57066   if (!this.options.mangle) return text;
57067   var out = ''
57068     , l = text.length
57069     , i = 0
57070     , ch;
57071
57072   for (; i < l; i++) {
57073     ch = text.charCodeAt(i);
57074     if (Math.random() > 0.5) {
57075       ch = 'x' + ch.toString(16);
57076     }
57077     out += '&#' + ch + ';';
57078   }
57079
57080   return out;
57081 };
57082
57083 /**
57084  * Renderer
57085  */
57086
57087 function Renderer(options) {
57088   this.options = options || {};
57089 }
57090
57091 Renderer.prototype.code = function(code, lang, escaped) {
57092   if (this.options.highlight) {
57093     var out = this.options.highlight(code, lang);
57094     if (out != null && out !== code) {
57095       escaped = true;
57096       code = out;
57097     }
57098   }
57099
57100   if (!lang) {
57101     return '<pre><code>'
57102       + (escaped ? code : escape(code, true))
57103       + '\n</code></pre>';
57104   }
57105
57106   return '<pre><code class="'
57107     + this.options.langPrefix
57108     + escape(lang, true)
57109     + '">'
57110     + (escaped ? code : escape(code, true))
57111     + '\n</code></pre>\n';
57112 };
57113
57114 Renderer.prototype.blockquote = function(quote) {
57115   return '<blockquote>\n' + quote + '</blockquote>\n';
57116 };
57117
57118 Renderer.prototype.html = function(html) {
57119   return html;
57120 };
57121
57122 Renderer.prototype.heading = function(text, level, raw) {
57123   return '<h'
57124     + level
57125     + ' id="'
57126     + this.options.headerPrefix
57127     + raw.toLowerCase().replace(/[^\w]+/g, '-')
57128     + '">'
57129     + text
57130     + '</h'
57131     + level
57132     + '>\n';
57133 };
57134
57135 Renderer.prototype.hr = function() {
57136   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
57137 };
57138
57139 Renderer.prototype.list = function(body, ordered) {
57140   var type = ordered ? 'ol' : 'ul';
57141   return '<' + type + '>\n' + body + '</' + type + '>\n';
57142 };
57143
57144 Renderer.prototype.listitem = function(text) {
57145   return '<li>' + text + '</li>\n';
57146 };
57147
57148 Renderer.prototype.paragraph = function(text) {
57149   return '<p>' + text + '</p>\n';
57150 };
57151
57152 Renderer.prototype.table = function(header, body) {
57153   return '<table>\n'
57154     + '<thead>\n'
57155     + header
57156     + '</thead>\n'
57157     + '<tbody>\n'
57158     + body
57159     + '</tbody>\n'
57160     + '</table>\n';
57161 };
57162
57163 Renderer.prototype.tablerow = function(content) {
57164   return '<tr>\n' + content + '</tr>\n';
57165 };
57166
57167 Renderer.prototype.tablecell = function(content, flags) {
57168   var type = flags.header ? 'th' : 'td';
57169   var tag = flags.align
57170     ? '<' + type + ' style="text-align:' + flags.align + '">'
57171     : '<' + type + '>';
57172   return tag + content + '</' + type + '>\n';
57173 };
57174
57175 // span level renderer
57176 Renderer.prototype.strong = function(text) {
57177   return '<strong>' + text + '</strong>';
57178 };
57179
57180 Renderer.prototype.em = function(text) {
57181   return '<em>' + text + '</em>';
57182 };
57183
57184 Renderer.prototype.codespan = function(text) {
57185   return '<code>' + text + '</code>';
57186 };
57187
57188 Renderer.prototype.br = function() {
57189   return this.options.xhtml ? '<br/>' : '<br>';
57190 };
57191
57192 Renderer.prototype.del = function(text) {
57193   return '<del>' + text + '</del>';
57194 };
57195
57196 Renderer.prototype.link = function(href, title, text) {
57197   if (this.options.sanitize) {
57198     try {
57199       var prot = decodeURIComponent(unescape(href))
57200         .replace(/[^\w:]/g, '')
57201         .toLowerCase();
57202     } catch (e) {
57203       return '';
57204     }
57205     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
57206       return '';
57207     }
57208   }
57209   var out = '<a href="' + href + '"';
57210   if (title) {
57211     out += ' title="' + title + '"';
57212   }
57213   out += '>' + text + '</a>';
57214   return out;
57215 };
57216
57217 Renderer.prototype.image = function(href, title, text) {
57218   var out = '<img src="' + href + '" alt="' + text + '"';
57219   if (title) {
57220     out += ' title="' + title + '"';
57221   }
57222   out += this.options.xhtml ? '/>' : '>';
57223   return out;
57224 };
57225
57226 Renderer.prototype.text = function(text) {
57227   return text;
57228 };
57229
57230 /**
57231  * Parsing & Compiling
57232  */
57233
57234 function Parser(options) {
57235   this.tokens = [];
57236   this.token = null;
57237   this.options = options || marked.defaults;
57238   this.options.renderer = this.options.renderer || new Renderer;
57239   this.renderer = this.options.renderer;
57240   this.renderer.options = this.options;
57241 }
57242
57243 /**
57244  * Static Parse Method
57245  */
57246
57247 Parser.parse = function(src, options, renderer) {
57248   var parser = new Parser(options, renderer);
57249   return parser.parse(src);
57250 };
57251
57252 /**
57253  * Parse Loop
57254  */
57255
57256 Parser.prototype.parse = function(src) {
57257   this.inline = new InlineLexer(src.links, this.options, this.renderer);
57258   this.tokens = src.reverse();
57259
57260   var out = '';
57261   while (this.next()) {
57262     out += this.tok();
57263   }
57264
57265   return out;
57266 };
57267
57268 /**
57269  * Next Token
57270  */
57271
57272 Parser.prototype.next = function() {
57273   return this.token = this.tokens.pop();
57274 };
57275
57276 /**
57277  * Preview Next Token
57278  */
57279
57280 Parser.prototype.peek = function() {
57281   return this.tokens[this.tokens.length - 1] || 0;
57282 };
57283
57284 /**
57285  * Parse Text Tokens
57286  */
57287
57288 Parser.prototype.parseText = function() {
57289   var body = this.token.text;
57290
57291   while (this.peek().type === 'text') {
57292     body += '\n' + this.next().text;
57293   }
57294
57295   return this.inline.output(body);
57296 };
57297
57298 /**
57299  * Parse Current Token
57300  */
57301
57302 Parser.prototype.tok = function() {
57303   switch (this.token.type) {
57304     case 'space': {
57305       return '';
57306     }
57307     case 'hr': {
57308       return this.renderer.hr();
57309     }
57310     case 'heading': {
57311       return this.renderer.heading(
57312         this.inline.output(this.token.text),
57313         this.token.depth,
57314         this.token.text);
57315     }
57316     case 'code': {
57317       return this.renderer.code(this.token.text,
57318         this.token.lang,
57319         this.token.escaped);
57320     }
57321     case 'table': {
57322       var header = ''
57323         , body = ''
57324         , i
57325         , row
57326         , cell
57327         , flags
57328         , j;
57329
57330       // header
57331       cell = '';
57332       for (i = 0; i < this.token.header.length; i++) {
57333         flags = { header: true, align: this.token.align[i] };
57334         cell += this.renderer.tablecell(
57335           this.inline.output(this.token.header[i]),
57336           { header: true, align: this.token.align[i] }
57337         );
57338       }
57339       header += this.renderer.tablerow(cell);
57340
57341       for (i = 0; i < this.token.cells.length; i++) {
57342         row = this.token.cells[i];
57343
57344         cell = '';
57345         for (j = 0; j < row.length; j++) {
57346           cell += this.renderer.tablecell(
57347             this.inline.output(row[j]),
57348             { header: false, align: this.token.align[j] }
57349           );
57350         }
57351
57352         body += this.renderer.tablerow(cell);
57353       }
57354       return this.renderer.table(header, body);
57355     }
57356     case 'blockquote_start': {
57357       var body = '';
57358
57359       while (this.next().type !== 'blockquote_end') {
57360         body += this.tok();
57361       }
57362
57363       return this.renderer.blockquote(body);
57364     }
57365     case 'list_start': {
57366       var body = ''
57367         , ordered = this.token.ordered;
57368
57369       while (this.next().type !== 'list_end') {
57370         body += this.tok();
57371       }
57372
57373       return this.renderer.list(body, ordered);
57374     }
57375     case 'list_item_start': {
57376       var body = '';
57377
57378       while (this.next().type !== 'list_item_end') {
57379         body += this.token.type === 'text'
57380           ? this.parseText()
57381           : this.tok();
57382       }
57383
57384       return this.renderer.listitem(body);
57385     }
57386     case 'loose_item_start': {
57387       var body = '';
57388
57389       while (this.next().type !== 'list_item_end') {
57390         body += this.tok();
57391       }
57392
57393       return this.renderer.listitem(body);
57394     }
57395     case 'html': {
57396       var html = !this.token.pre && !this.options.pedantic
57397         ? this.inline.output(this.token.text)
57398         : this.token.text;
57399       return this.renderer.html(html);
57400     }
57401     case 'paragraph': {
57402       return this.renderer.paragraph(this.inline.output(this.token.text));
57403     }
57404     case 'text': {
57405       return this.renderer.paragraph(this.parseText());
57406     }
57407   }
57408 };
57409
57410 /**
57411  * Helpers
57412  */
57413
57414 function escape(html, encode) {
57415   return html
57416     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
57417     .replace(/</g, '&lt;')
57418     .replace(/>/g, '&gt;')
57419     .replace(/"/g, '&quot;')
57420     .replace(/'/g, '&#39;');
57421 }
57422
57423 function unescape(html) {
57424         // explicitly match decimal, hex, and named HTML entities 
57425   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
57426     n = n.toLowerCase();
57427     if (n === 'colon') return ':';
57428     if (n.charAt(0) === '#') {
57429       return n.charAt(1) === 'x'
57430         ? String.fromCharCode(parseInt(n.substring(2), 16))
57431         : String.fromCharCode(+n.substring(1));
57432     }
57433     return '';
57434   });
57435 }
57436
57437 function replace(regex, opt) {
57438   regex = regex.source;
57439   opt = opt || '';
57440   return function self(name, val) {
57441     if (!name) return new RegExp(regex, opt);
57442     val = val.source || val;
57443     val = val.replace(/(^|[^\[])\^/g, '$1');
57444     regex = regex.replace(name, val);
57445     return self;
57446   };
57447 }
57448
57449 function noop() {}
57450 noop.exec = noop;
57451
57452 function merge(obj) {
57453   var i = 1
57454     , target
57455     , key;
57456
57457   for (; i < arguments.length; i++) {
57458     target = arguments[i];
57459     for (key in target) {
57460       if (Object.prototype.hasOwnProperty.call(target, key)) {
57461         obj[key] = target[key];
57462       }
57463     }
57464   }
57465
57466   return obj;
57467 }
57468
57469
57470 /**
57471  * Marked
57472  */
57473
57474 function marked(src, opt, callback) {
57475   if (callback || typeof opt === 'function') {
57476     if (!callback) {
57477       callback = opt;
57478       opt = null;
57479     }
57480
57481     opt = merge({}, marked.defaults, opt || {});
57482
57483     var highlight = opt.highlight
57484       , tokens
57485       , pending
57486       , i = 0;
57487
57488     try {
57489       tokens = Lexer.lex(src, opt);
57490     } catch (e) {
57491       return callback(e);
57492     }
57493
57494     pending = tokens.length;
57495
57496     var done = function(err) {
57497       if (err) {
57498         opt.highlight = highlight;
57499         return callback(err);
57500       }
57501
57502       var out;
57503
57504       try {
57505         out = Parser.parse(tokens, opt);
57506       } catch (e) {
57507         err = e;
57508       }
57509
57510       opt.highlight = highlight;
57511
57512       return err
57513         ? callback(err)
57514         : callback(null, out);
57515     };
57516
57517     if (!highlight || highlight.length < 3) {
57518       return done();
57519     }
57520
57521     delete opt.highlight;
57522
57523     if (!pending) return done();
57524
57525     for (; i < tokens.length; i++) {
57526       (function(token) {
57527         if (token.type !== 'code') {
57528           return --pending || done();
57529         }
57530         return highlight(token.text, token.lang, function(err, code) {
57531           if (err) return done(err);
57532           if (code == null || code === token.text) {
57533             return --pending || done();
57534           }
57535           token.text = code;
57536           token.escaped = true;
57537           --pending || done();
57538         });
57539       })(tokens[i]);
57540     }
57541
57542     return;
57543   }
57544   try {
57545     if (opt) opt = merge({}, marked.defaults, opt);
57546     return Parser.parse(Lexer.lex(src, opt), opt);
57547   } catch (e) {
57548     e.message += '\nPlease report this to https://github.com/chjj/marked.';
57549     if ((opt || marked.defaults).silent) {
57550       return '<p>An error occured:</p><pre>'
57551         + escape(e.message + '', true)
57552         + '</pre>';
57553     }
57554     throw e;
57555   }
57556 }
57557
57558 /**
57559  * Options
57560  */
57561
57562 marked.options =
57563 marked.setOptions = function(opt) {
57564   merge(marked.defaults, opt);
57565   return marked;
57566 };
57567
57568 marked.defaults = {
57569   gfm: true,
57570   tables: true,
57571   breaks: false,
57572   pedantic: false,
57573   sanitize: false,
57574   sanitizer: null,
57575   mangle: true,
57576   smartLists: false,
57577   silent: false,
57578   highlight: null,
57579   langPrefix: 'lang-',
57580   smartypants: false,
57581   headerPrefix: '',
57582   renderer: new Renderer,
57583   xhtml: false
57584 };
57585
57586 /**
57587  * Expose
57588  */
57589
57590 marked.Parser = Parser;
57591 marked.parser = Parser.parse;
57592
57593 marked.Renderer = Renderer;
57594
57595 marked.Lexer = Lexer;
57596 marked.lexer = Lexer.lex;
57597
57598 marked.InlineLexer = InlineLexer;
57599 marked.inlineLexer = InlineLexer.output;
57600
57601 marked.parse = marked;
57602
57603 {
57604   module.exports = marked;
57605 }
57606
57607 }).call(function() {
57608   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
57609 }());
57610 });
57611
57612 // toggles the visibility of ui elements, using a combination of the
57613 // hide class, which sets display=none, and a d3 transition for opacity.
57614 // this will cause blinking when called repeatedly, so check that the
57615 // value actually changes between calls.
57616 function uiToggle(show, callback) {
57617     return function(selection$$1) {
57618         selection$$1
57619             .style('opacity', show ? 0 : 1)
57620             .classed('hide', false)
57621             .transition()
57622             .style('opacity', show ? 1 : 0)
57623             .on('end', function() {
57624                 select(this)
57625                     .classed('hide', !show)
57626                     .style('opacity', null);
57627                 if (callback) callback.apply(this);
57628             });
57629     };
57630 }
57631
57632 // Tooltips and svg mask used to highlight certain features
57633 function d3curtain() {
57634
57635     var dispatch$$1 = dispatch(),
57636         surface = select(null),
57637         tooltip = select(null),
57638         darkness = select(null);
57639
57640     function curtain(selection$$1) {
57641         surface = selection$$1
57642             .append('svg')
57643             .attr('id', 'curtain')
57644             .style('z-index', 1000)
57645             .style('pointer-events', 'none')
57646             .style('position', 'absolute')
57647             .style('top', 0)
57648             .style('left', 0);
57649
57650         darkness = surface.append('path')
57651             .attr('x', 0)
57652             .attr('y', 0)
57653             .attr('class', 'curtain-darkness');
57654
57655         select(window).on('resize.curtain', resize);
57656
57657         tooltip = selection$$1.append('div')
57658             .attr('class', 'tooltip')
57659             .style('z-index', 1002);
57660
57661         tooltip
57662             .append('div')
57663             .attr('class', 'tooltip-arrow');
57664
57665         tooltip
57666             .append('div')
57667             .attr('class', 'tooltip-inner');
57668
57669         resize();
57670
57671
57672         function resize() {
57673             surface
57674                 .attr('width', window.innerWidth)
57675                 .attr('height', window.innerHeight);
57676             curtain.cut(darkness.datum());
57677         }
57678     }
57679
57680
57681     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
57682         if (typeof box === 'string') box = select(box).node();
57683         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
57684
57685         curtain.cut(box, duration);
57686
57687         if (text$$1) {
57688             // pseudo markdown bold text hack
57689             var parts = text$$1.split('**');
57690             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
57691             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
57692
57693             var selection$$1 = tooltip
57694                 .classed('in', true)
57695                 .selectAll('.tooltip-inner')
57696                 .html(html$$1);
57697
57698             var dimensions = utilGetDimensions(selection$$1, true),
57699                 w = window.innerWidth,
57700                 h = window.innerHeight,
57701                 side, pos;
57702
57703             // trim box dimensions to just the portion that fits in the window..
57704             if (box.top + box.height > h) {
57705                 box.height -= (box.top + box.height - h);
57706             }
57707             if (box.left + box.width > w) {
57708                 box.width -= (box.left + box.width - w);
57709             }
57710
57711             // determine tooltip placement..
57712             if (box.top + box.height < Math.min(100, box.width + box.left)) {
57713                 side = 'bottom';
57714                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
57715
57716             } else if (box.left + box.width + 300 < w) {
57717                 side = 'right';
57718                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
57719
57720             } else if (box.left > 300) {
57721                 side = 'left';
57722                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
57723
57724             } else {
57725                 side = 'bottom';
57726                 pos = [box.left, box.top + box.height];
57727             }
57728
57729             pos = [
57730                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
57731                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
57732             ];
57733
57734             if (duration !== 0 || !tooltip.classed(side)) {
57735                 tooltip.call(uiToggle(true));
57736             }
57737
57738             tooltip
57739                 .style('top', pos[1] + 'px')
57740                 .style('left', pos[0] + 'px')
57741                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
57742
57743         } else {
57744             tooltip.call(uiToggle(false));
57745         }
57746     };
57747
57748
57749     curtain.cut = function(datum, duration) {
57750         darkness.datum(datum)
57751             .interrupt();
57752
57753         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
57754             .attr('d', function(d) {
57755                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
57756                     window.innerWidth + ',' + window.innerHeight + 'L' +
57757                     window.innerWidth + ',0 Z';
57758
57759                 if (!d) return string;
57760                 return string + 'M' +
57761                     d.left + ',' + d.top + 'L' +
57762                     d.left + ',' + (d.top + d.height) + 'L' +
57763                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
57764                     (d.left + d.width) + ',' + (d.top) + 'Z';
57765
57766             });
57767     };
57768
57769
57770     curtain.remove = function() {
57771         surface.remove();
57772         tooltip.remove();
57773     };
57774
57775
57776     return utilRebind(curtain, dispatch$$1, 'on');
57777 }
57778
57779 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"]}};
57780
57781 function pointBox(point, context) {
57782     var rect = context.surfaceRect();
57783     point = context.projection(point);
57784     return {
57785         left: point[0] + rect.left - 30,
57786         top: point[1] + rect.top - 50,
57787         width: 60,
57788         height: 70
57789      };
57790 }
57791
57792
57793 function pad$1(box, padding, context) {
57794     if (box instanceof Array) {
57795         var rect = context.surfaceRect();
57796         box = context.projection(box);
57797         box = {
57798             left: box[0] + rect.left,
57799             top: box[1] + rect.top
57800         };
57801     }
57802     return {
57803         left: box.left - padding,
57804         top: box.top - padding,
57805         width: (box.width || 0) + 2 * padding,
57806         height: (box.width || 0) + 2 * padding
57807     };
57808 }
57809
57810
57811 function icon(name, svgklass) {
57812     return '<svg class="icon ' + (svgklass || '') + '">' +
57813          '<use xlink:href="' + name + '"></use></svg>';
57814  }
57815
57816 function uiIntroNavigation(context, reveal) {
57817     var dispatch$$1 = dispatch('done'),
57818         timeouts = [];
57819
57820     var step = {
57821         title: 'intro.navigation.title'
57822     };
57823
57824
57825     function set$$1(f, t$$1) {
57826         timeouts.push(window.setTimeout(f, t$$1));
57827     }
57828
57829
57830     function eventCancel() {
57831         event.stopPropagation();
57832         event.preventDefault();
57833     }
57834
57835
57836     step.enter = function() {
57837         var rect = context.surfaceRect(),
57838             map$$1 = {
57839                 left: rect.left + 10,
57840                 top: rect.top + 70,
57841                 width: rect.width - 70,
57842                 height: rect.height - 170
57843             };
57844
57845         context.map().centerZoom([-85.63591, 41.94285], 19);
57846
57847         reveal(map$$1, t('intro.navigation.drag'));
57848
57849         context.map().on('move.intro', lodash.debounce(function() {
57850             context.map().on('move.intro', null);
57851             townhall();
57852             context.on('enter.intro', inspectTownHall);
57853         }, 400));
57854
57855
57856         function townhall() {
57857             var hall = [-85.63645945147184, 41.942986488012565];
57858             var point = context.projection(hall);
57859
57860             if (point[0] < 0 || point[0] > rect.width ||
57861                 point[1] < 0 || point[1] > rect.height) {
57862                 context.map().center(hall);
57863             }
57864
57865             var box = pointBox(hall, context);
57866             reveal(box, t('intro.navigation.select'));
57867
57868             context.map().on('move.intro', function() {
57869                 var box = pointBox(hall, context);
57870                 reveal(box, t('intro.navigation.select'), {duration: 0});
57871             });
57872         }
57873
57874
57875         function inspectTownHall(mode) {
57876             if (mode.id !== 'select') return;
57877             context.on('enter.intro', null);
57878             context.map().on('move.intro', null);
57879             set$$1(function() {
57880                 reveal('.entity-editor-pane',
57881                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
57882                 context.on('exit.intro', streetSearch);
57883             }, 700);
57884         }
57885
57886
57887         function streetSearch() {
57888             context.on('exit.intro', null);
57889             reveal('.search-header input',
57890                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
57891             select('.search-header input')
57892                 .on('keyup.intro', searchResult);
57893         }
57894
57895
57896         function searchResult() {
57897             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
57898                 firstName = first.select('.entity-name'),
57899                 name = t('intro.graph.spring_st');
57900
57901             if (!firstName.empty() && firstName.text() === name) {
57902                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
57903                 context.on('exit.intro', selectedStreet);
57904                 select('.search-header input')
57905                     .on('keydown.intro', eventCancel, true)
57906                     .on('keyup.intro', null);
57907             }
57908         }
57909
57910
57911         function selectedStreet() {
57912             var springSt = [-85.63585099140167, 41.942506848938926];
57913             context.map().center(springSt);
57914             context.on('exit.intro', function() {
57915                 dispatch$$1.call('done');
57916             });
57917
57918             set$$1(function() {
57919                 reveal('.entity-editor-pane',
57920                     t('intro.navigation.chosen', {
57921                         name: t('intro.graph.spring_st'),
57922                         button: icon('#icon-close', 'pre-text')
57923                     }));
57924             }, 400);
57925         }
57926     };
57927
57928
57929     step.exit = function() {
57930         timeouts.forEach(window.clearTimeout);
57931         context.map().on('move.intro', null);
57932         context.on('enter.intro', null);
57933         context.on('exit.intro', null);
57934         select('.search-header input')
57935             .on('keydown.intro', null)
57936             .on('keyup.intro', null);
57937     };
57938
57939
57940     return utilRebind(step, dispatch$$1, 'on');
57941 }
57942
57943 function uiIntroPoint(context, reveal) {
57944     var dispatch$$1 = dispatch('done'),
57945         timeouts = [];
57946
57947     var step = {
57948         title: 'intro.points.title'
57949     };
57950
57951
57952     function setTimeout(f, t$$1) {
57953         timeouts.push(window.setTimeout(f, t$$1));
57954     }
57955
57956
57957     function eventCancel() {
57958         event.stopPropagation();
57959         event.preventDefault();
57960     }
57961
57962
57963     step.enter = function() {
57964         context.map().centerZoom([-85.63279, 41.94394], 19);
57965         reveal('button.add-point',
57966             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
57967             { tooltipClass: 'intro-points-add' });
57968
57969         var corner = [-85.632481,41.944094];
57970
57971         context.on('enter.intro', addPoint);
57972
57973
57974         function addPoint(mode) {
57975             if (mode.id !== 'add-point') return;
57976             context.on('enter.intro', enterSelect);
57977
57978             var pointBox$$1 = pad$1(corner, 150, context);
57979             reveal(pointBox$$1, t('intro.points.place'));
57980
57981             context.map().on('move.intro', function() {
57982                 pointBox$$1 = pad$1(corner, 150, context);
57983                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
57984             });
57985         }
57986
57987
57988         function enterSelect(mode) {
57989             if (mode.id !== 'select') return;
57990             context.map().on('move.intro', null);
57991             context.on('enter.intro', null);
57992
57993             setTimeout(function() {
57994                 reveal('.preset-search-input',
57995                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
57996                 select('.preset-search-input').on('keyup.intro', keySearch);
57997             }, 500);
57998         }
57999
58000
58001         function keySearch() {
58002             var first = select('.preset-list-item:first-child');
58003             if (first.classed('preset-amenity-cafe')) {
58004                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
58005                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
58006                 select('.preset-search-input')
58007                     .on('keydown.intro', eventCancel, true)
58008                     .on('keyup.intro', null);
58009             }
58010         }
58011
58012
58013         function selectedPreset() {
58014             setTimeout(function() {
58015                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
58016                 context.history().on('change.intro', closeEditor);
58017                 context.on('exit.intro', selectPoint);
58018             }, 400);
58019         }
58020
58021
58022         function closeEditor() {
58023             select('.preset-search-input').on('keydown.intro', null);
58024             context.history().on('change.intro', null);
58025             reveal('.entity-editor-pane',
58026                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
58027         }
58028
58029
58030         function selectPoint() {
58031             context.on('exit.intro', null);
58032             context.history().on('change.intro', null);
58033             context.on('enter.intro', enterReselect);
58034
58035             var pointBox$$1 = pad$1(corner, 150, context);
58036             reveal(pointBox$$1, t('intro.points.reselect'));
58037
58038             context.map().on('move.intro', function() {
58039                 pointBox$$1 = pad$1(corner, 150, context);
58040                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
58041             });
58042         }
58043
58044
58045         function enterReselect(mode) {
58046             if (mode.id !== 'select') return;
58047             context.map().on('move.intro', null);
58048             context.on('enter.intro', null);
58049
58050             setTimeout(function() {
58051                 reveal('.entity-editor-pane',
58052                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
58053                 context.on('exit.intro', deletePoint);
58054             }, 500);
58055         }
58056
58057
58058         function deletePoint() {
58059             context.on('exit.intro', null);
58060             context.on('enter.intro', enterDelete);
58061
58062             var pointBox$$1 = pad$1(corner, 150, context);
58063             reveal(pointBox$$1, t('intro.points.reselect_delete'));
58064
58065             context.map().on('move.intro', function() {
58066                 pointBox$$1 = pad$1(corner, 150, context);
58067                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
58068             });
58069         }
58070
58071
58072         function enterDelete(mode) {
58073             if (mode.id !== 'select') return;
58074             context.map().on('move.intro', null);
58075             context.on('enter.intro', null);
58076             context.on('exit.intro', deletePoint);
58077             context.map().on('move.intro', deletePoint);
58078             context.history().on('change.intro', deleted);
58079
58080             setTimeout(function() {
58081                 var node = select('.radial-menu-item-delete').node();
58082                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
58083                 reveal(pointBox$$1,
58084                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
58085             }, 300);
58086         }
58087
58088
58089         function deleted(changed) {
58090             if (changed.deleted().length) {
58091                 dispatch$$1.call('done');
58092             }
58093         }
58094
58095     };
58096
58097
58098     step.exit = function() {
58099         timeouts.forEach(window.clearTimeout);
58100         context.on('exit.intro', null);
58101         context.on('enter.intro', null);
58102         context.map().on('move.intro', null);
58103         context.history().on('change.intro', null);
58104         select('.preset-search-input')
58105             .on('keyup.intro', null)
58106             .on('keydown.intro', null);
58107     };
58108
58109     return utilRebind(step, dispatch$$1, 'on');
58110 }
58111
58112 function uiIntroArea(context, reveal) {
58113     var dispatch$$1 = dispatch('done'),
58114         timeout$$1;
58115
58116     var step = {
58117         title: 'intro.areas.title'
58118     };
58119
58120
58121     step.enter = function() {
58122         var playground = [-85.63552, 41.94159],
58123             corner = [-85.63565411045074, 41.9417715536927];
58124         context.map().centerZoom(playground, 19);
58125         reveal('button.add-area',
58126             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
58127             { tooltipClass: 'intro-areas-add' });
58128
58129         context.on('enter.intro', addArea);
58130
58131
58132         function addArea(mode) {
58133             if (mode.id !== 'add-area') return;
58134             context.on('enter.intro', drawArea);
58135
58136             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
58137             var pointBox$$1 = pad$1(corner, padding, context);
58138             reveal(pointBox$$1, t('intro.areas.corner'));
58139
58140             context.map().on('move.intro', function() {
58141                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
58142                 pointBox$$1 = pad$1(corner, padding, context);
58143                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
58144             });
58145         }
58146
58147
58148         function drawArea(mode) {
58149             if (mode.id !== 'draw-area') return;
58150             context.on('enter.intro', enterSelect);
58151
58152             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
58153             var pointBox$$1 = pad$1(playground, padding, context);
58154             reveal(pointBox$$1, t('intro.areas.place'));
58155
58156             context.map().on('move.intro', function() {
58157                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
58158                 pointBox$$1 = pad$1(playground, padding, context);
58159                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
58160             });
58161         }
58162
58163
58164         function enterSelect(mode) {
58165             if (mode.id !== 'select') return;
58166             context.map().on('move.intro', null);
58167             context.on('enter.intro', null);
58168
58169             timeout$$1 = setTimeout(function() {
58170                 reveal('.preset-search-input',
58171                     t('intro.areas.search',
58172                     { name: context.presets().item('leisure/playground').name() }));
58173                 select('.preset-search-input').on('keyup.intro', keySearch);
58174             }, 500);
58175         }
58176
58177
58178         function keySearch() {
58179             var first = select('.preset-list-item:first-child');
58180             if (first.classed('preset-leisure-playground')) {
58181                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
58182                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
58183                 select('.preset-search-input').on('keyup.intro', null);
58184             }
58185         }
58186
58187
58188         function selectedPreset() {
58189             reveal('.pane',
58190                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
58191             context.on('exit.intro', function() {
58192                 dispatch$$1.call('done');
58193             });
58194         }
58195     };
58196
58197
58198     step.exit = function() {
58199         window.clearTimeout(timeout$$1);
58200         context.on('enter.intro', null);
58201         context.on('exit.intro', null);
58202         context.history().on('change.intro', null);
58203         context.map().on('move.intro', null);
58204         select('.preset-search-input').on('keyup.intro', null);
58205     };
58206
58207
58208     return utilRebind(step, dispatch$$1, 'on');
58209 }
58210
58211 function uiIntroLine(context, reveal) {
58212     var dispatch$$1 = dispatch('done'),
58213         timeouts = [],
58214         centroid = [-85.62830, 41.95699],
58215         midpoint = [-85.62975395449628, 41.95787501510204],
58216         start = [-85.6297754121684, 41.95805253325314],
58217         intersection = [-85.62974496187628, 41.95742515554585],
58218         targetId = 'w17965351',
58219         drawId = null;
58220
58221
58222     var step = {
58223         title: 'intro.lines.title'
58224     };
58225
58226
58227     function timeout$$1(f, t$$1) {
58228         timeouts.push(window.setTimeout(f, t$$1));
58229     }
58230
58231
58232     function eventCancel() {
58233         event.stopPropagation();
58234         event.preventDefault();
58235     }
58236
58237
58238     step.enter = function() {
58239         context.map().centerZoom(start, 18);
58240         reveal('button.add-line',
58241             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
58242             { tooltipClass: 'intro-lines-add' });
58243
58244         context.on('enter.intro', addLine);
58245
58246
58247         function addLine(mode) {
58248             if (mode.id !== 'add-line') return;
58249             drawId = null;
58250             context.on('enter.intro', drawLine);
58251
58252             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
58253             var pointBox$$1 = pad$1(start, padding, context);
58254             reveal(pointBox$$1, t('intro.lines.start'));
58255
58256             context.map().on('move.intro', function() {
58257                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
58258                 pointBox$$1 = pad$1(start, padding, context);
58259                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
58260             });
58261         }
58262
58263
58264         function drawLine(mode) {
58265             if (mode.id !== 'draw-line') return;
58266             drawId = mode.selectedIDs()[0];
58267             context.history().on('change.intro', checkIntersection);
58268             context.on('enter.intro', retry);
58269
58270             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
58271             var pointBox$$1 = pad$1(midpoint, padding, context);
58272             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
58273
58274             context.map().on('move.intro', function() {
58275                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
58276                 pointBox$$1 = pad$1(midpoint, padding, context);
58277                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
58278             });
58279         }
58280
58281
58282         // ended line before creating intersection
58283         function retry(mode) {
58284             if (mode.id !== 'select') return;
58285             context.history().on('change.intro', null);
58286             var pointBox$$1 = pad$1(intersection, 30, context);
58287             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
58288             select(window).on('mousedown.intro', eventCancel, true);
58289
58290             timeout$$1(step.restart, 3000);
58291         }
58292
58293
58294         function checkIntersection() {
58295
58296             function joinedTargetWay() {
58297                 var drawEntity = drawId && context.hasEntity(drawId);
58298                 if (!drawEntity) {
58299                     step.restart();
58300                     return false;
58301                 }
58302
58303                 var drawNodes = context.graph().childNodes(drawEntity);
58304                 return lodash.some(drawNodes, function(node) {
58305                     return lodash.some(context.graph().parentWays(node), function(parent) {
58306                         return parent.id === targetId;
58307                     });
58308                 });
58309             }
58310
58311             if (joinedTargetWay()) {
58312                 context.history().on('change.intro', null);
58313                 context.on('enter.intro', enterSelect);
58314
58315                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
58316                 var pointBox$$1 = pad$1(centroid, padding, context);
58317                 reveal(pointBox$$1, t('intro.lines.finish'));
58318
58319                 context.map().on('move.intro', function() {
58320                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
58321                     pointBox$$1 = pad$1(centroid, padding, context);
58322                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
58323                 });
58324             }
58325         }
58326
58327
58328         function enterSelect(mode) {
58329             if (mode.id !== 'select') return;
58330             context.map().on('move.intro', null);
58331             context.on('enter.intro', null);
58332             select('#curtain').style('pointer-events', 'all');
58333             presetCategory();
58334         }
58335
58336
58337         function presetCategory() {
58338             timeout$$1(function() {
58339                 select('#curtain').style('pointer-events', 'none');
58340                 var road = select('.preset-category-road .preset-list-button');
58341                 reveal(road.node(), t('intro.lines.road'));
58342                 utilBindOnce(road, 'click.intro', roadCategory);
58343             }, 500);
58344         }
58345
58346
58347         function roadCategory() {
58348             timeout$$1(function() {
58349                 var grid = select('.subgrid');
58350                 reveal(grid.node(), t('intro.lines.residential'));
58351                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
58352                     'click.intro', retryPreset);
58353                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
58354                     'click.intro', roadDetails);
58355             }, 500);
58356         }
58357
58358
58359         // selected wrong road type
58360         function retryPreset() {
58361             timeout$$1(function() {
58362                 var preset = select('.entity-editor-pane .preset-list-button');
58363                 reveal(preset.node(), t('intro.lines.wrong_preset'));
58364                 utilBindOnce(preset, 'click.intro', presetCategory);
58365             }, 500);
58366         }
58367
58368
58369         function roadDetails() {
58370             reveal('.pane',
58371                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
58372             context.on('exit.intro', function() {
58373                 dispatch$$1.call('done');
58374             });
58375         }
58376     };
58377
58378
58379     step.restart = function() {
58380         step.exit();
58381         step.enter();
58382     };
58383
58384
58385     step.exit = function() {
58386         select(window).on('mousedown.intro', null, true);
58387         select('#curtain').style('pointer-events', 'none');
58388         timeouts.forEach(window.clearTimeout);
58389         context.on('enter.intro', null);
58390         context.on('exit.intro', null);
58391         context.map().on('move.intro', null);
58392         context.history().on('change.intro', null);
58393         if (drawId) {
58394             context.replace(actionDeleteMultiple([drawId]));
58395             drawId = null;
58396         }
58397     };
58398
58399     return utilRebind(step, dispatch$$1, 'on');
58400 }
58401
58402 function uiIntroStartEditing(context, reveal) {
58403     var dispatch$$1 = dispatch('done', 'startEditing'),
58404         modalSelection,
58405         timeouts = [];
58406
58407     var step = {
58408         title: 'intro.startediting.title'
58409     };
58410
58411
58412     function timeout$$1(f, t$$1) {
58413         timeouts.push(window.setTimeout(f, t$$1));
58414     }
58415
58416
58417     step.enter = function() {
58418         reveal('.map-control.help-control',
58419             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
58420
58421         timeout$$1(function() {
58422             reveal('#bar button.save', t('intro.startediting.save'));
58423         }, 5000);
58424
58425         timeout$$1(function() {
58426             reveal('#surface');
58427         }, 10000);
58428
58429         timeout$$1(function() {
58430             modalSelection = uiModal(context.container());
58431
58432             modalSelection.select('.modal')
58433                 .attr('class', 'modal-splash modal col6');
58434
58435             modalSelection.selectAll('.close').remove();
58436
58437             var startbutton = modalSelection.select('.content')
58438                 .attr('class', 'fillL')
58439                 .append('button')
58440                     .attr('class', 'modal-section huge-modal-button')
58441                     .on('click', function() {
58442                         modalSelection.remove();
58443                     });
58444
58445                 startbutton
58446                     .append('div')
58447                     .attr('class','illustration');
58448
58449                 startbutton
58450                     .append('h2')
58451                     .text(t('intro.startediting.start'));
58452
58453             dispatch$$1.call('startEditing');
58454         }, 10500);
58455     };
58456
58457
58458     step.exit = function() {
58459         if (modalSelection) { modalSelection.remove(); }
58460         timeouts.forEach(window.clearTimeout);
58461     };
58462
58463
58464     return utilRebind(step, dispatch$$1, 'on');
58465 }
58466
58467 var sampleIntros = {
58468     navigation: uiIntroNavigation,
58469     point: uiIntroPoint,
58470     area: uiIntroArea,
58471     line: uiIntroLine,
58472     startEditing: uiIntroStartEditing
58473 };
58474
58475
58476 function uiIntro(context) {
58477     var step;
58478
58479     function localizedName(id) {
58480         var features = {
58481             n2140018997: 'city_hall',
58482             n367813436: 'fire_department',
58483             w203988286: 'memory_isle_park',
58484             w203972937: 'riverwalk_trail',
58485             w203972938: 'riverwalk_trail',
58486             w203972940: 'riverwalk_trail',
58487             w41785752: 'w_michigan_ave',
58488             w134150789: 'w_michigan_ave',
58489             w134150795: 'w_michigan_ave',
58490             w134150800: 'w_michigan_ave',
58491             w134150811: 'w_michigan_ave',
58492             w134150802: 'e_michigan_ave',
58493             w134150836: 'e_michigan_ave',
58494             w41074896: 'e_michigan_ave',
58495             w17965834: 'spring_st',
58496             w203986457: 'scidmore_park',
58497             w203049587: 'petting_zoo',
58498             w17967397: 'n_andrews_st',
58499             w17967315: 's_andrews_st',
58500             w17967326: 'n_constantine_st',
58501             w17966400: 's_constantine_st',
58502             w170848823: 'rocky_river',
58503             w170848824: 'rocky_river',
58504             w170848331: 'rocky_river',
58505             w17967752: 'railroad_dr',
58506             w17965998: 'conrail_rr',
58507             w134150845: 'conrail_rr',
58508             w170989131: 'st_joseph_river',
58509             w143497377: 'n_main_st',
58510             w134150801: 's_main_st',
58511             w134150830: 's_main_st',
58512             w17966462: 's_main_st',
58513             w17967734: 'water_st',
58514             w17964996: 'foster_st',
58515             w170848330: 'portage_river',
58516             w17965351: 'flower_st',
58517             w17965502: 'elm_st',
58518             w17965402: 'walnut_st',
58519             w17964793: 'morris_ave',
58520             w17967444: 'east_st',
58521             w17966984: 'portage_ave'
58522         };
58523
58524         return features[id] && t('intro.graph.' + features[id]);
58525     }
58526
58527
58528     var introGraph = {};
58529
58530     for (var key in dataIntroGraph) {
58531         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
58532         var name = localizedName(key);
58533         if (name) {
58534             introGraph[key].tags.name = name;
58535         }
58536     }
58537
58538
58539     function intro(selection$$1) {
58540         context.enter(modeBrowse(context));
58541
58542         // Save current map state
58543         var history = context.history().toJSON(),
58544             hash = window.location.hash,
58545             center = context.map().center(),
58546             zoom$$1 = context.map().zoom(),
58547             background = context.background().baseLayerSource(),
58548             opacity = selectAll('#map .layer-background').style('opacity'),
58549             loadedTiles = context.connection().loadedTiles(),
58550             baseEntities = context.history().graph().base().entities;
58551
58552         // Block saving
58553         context.inIntro(true);
58554
58555         // Load semi-real data used in intro
58556         context.connection().toggle(false).reset();
58557         context.history().reset();
58558
58559         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
58560         context.background().bing();
58561
58562         selectAll('#map .layer-background').style('opacity', 1);
58563
58564         var curtain = d3curtain();
58565         selection$$1.call(curtain);
58566
58567
58568         function reveal(box, text$$1, options) {
58569             options = options || {};
58570             curtain.reveal(box,
58571                 text$$1 || '',
58572                 options.tooltipClass || '',
58573                 options.duration
58574             );
58575         }
58576
58577         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
58578             var s = sampleIntros[step](context, reveal)
58579                 .on('done', function() {
58580                     entered.filter(function(d) {
58581                         return d.title === s.title;
58582                     }).classed('finished', true);
58583                     enter(steps[i + 1]);
58584                 });
58585             return s;
58586         });
58587
58588         steps[steps.length - 1].on('startEditing', function() {
58589             curtain.remove();
58590             navwrap.remove();
58591             selectAll('#map .layer-background').style('opacity', opacity);
58592             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
58593             context.history().reset().merge(values(baseEntities));
58594             context.background().baseLayerSource(background);
58595             if (history) context.history().fromJSON(history, false);
58596             context.map().centerZoom(center, zoom$$1);
58597             window.location.replace(hash);
58598             context.inIntro(false);
58599         });
58600
58601         var navwrap = selection$$1
58602             .append('div')
58603             .attr('class', 'intro-nav-wrap fillD');
58604
58605         var buttonwrap = navwrap
58606             .append('div')
58607             .attr('class', 'joined')
58608             .selectAll('button.step');
58609
58610         var entered = buttonwrap
58611             .data(steps)
58612             .enter()
58613             .append('button')
58614             .attr('class', 'step')
58615             .on('click', enter);
58616
58617         entered
58618             .append('label')
58619             .text(function(d) { return t(d.title); });
58620
58621         entered
58622             .append('span')
58623             .attr('class', 'status')
58624             .text(' - ' + t('intro.done'));
58625
58626         enter(steps[0]);
58627
58628
58629         function enter(newStep) {
58630             if (step) { step.exit(); }
58631
58632             context.enter(modeBrowse(context));
58633
58634             step = newStep;
58635             step.enter();
58636
58637             entered.classed('active', function(d) {
58638                 return d.title === step.title;
58639             });
58640         }
58641
58642     }
58643
58644
58645     return intro;
58646 }
58647
58648 function uiHelp(context) {
58649     var key = 'H';
58650
58651     var docKeys = [
58652         'help.help',
58653         'help.editing_saving',
58654         'help.roads',
58655         'help.gps',
58656         'help.imagery',
58657         'help.addresses',
58658         'help.inspector',
58659         'help.buildings',
58660         'help.relations'];
58661
58662     var docs = docKeys.map(function(key) {
58663         var text$$1 = t(key);
58664         return {
58665             title: text$$1.split('\n')[0].replace('#', '').trim(),
58666             html: marked(text$$1.split('\n').slice(1).join('\n'))
58667         };
58668     });
58669
58670
58671     function help(selection$$1) {
58672
58673         function hide() {
58674             setVisible(false);
58675         }
58676
58677
58678         function toggle() {
58679             if (event) event.preventDefault();
58680             tooltipBehavior.hide(button);
58681             setVisible(!button.classed('active'));
58682         }
58683
58684
58685         function setVisible(show) {
58686             if (show !== shown) {
58687                 button.classed('active', show);
58688                 shown = show;
58689
58690                 if (show) {
58691                     selection$$1.on('mousedown.help-inside', function() {
58692                         return event.stopPropagation();
58693                     });
58694                     pane.style('display', 'block')
58695                         .style('right', '-500px')
58696                         .transition()
58697                         .duration(200)
58698                         .style('right', '0px');
58699                 } else {
58700                     pane.style('right', '0px')
58701                         .transition()
58702                         .duration(200)
58703                         .style('right', '-500px')
58704                         .on('end', function() {
58705                             select(this).style('display', 'none');
58706                         });
58707                     selection$$1.on('mousedown.help-inside', null);
58708                 }
58709             }
58710         }
58711
58712
58713         function clickHelp(d, i) {
58714             var rtl = (textDirection === 'rtl');
58715             pane.property('scrollTop', 0);
58716             doctitle.html(d.title);
58717
58718             body.html(d.html);
58719             body.selectAll('a')
58720                 .attr('target', '_blank');
58721             menuItems.classed('selected', function(m) {
58722                 return m.title === d.title;
58723             });
58724
58725             nav.html('');
58726             if (rtl) {
58727                 nav.call(drawNext).call(drawPrevious);
58728             } else {
58729                 nav.call(drawPrevious).call(drawNext);
58730             }
58731
58732
58733             function drawNext(selection$$1) {
58734                 if (i < docs.length - 1) {
58735                     var nextLink = selection$$1
58736                         .append('a')
58737                         .attr('class', 'next')
58738                         .on('click', function() {
58739                             clickHelp(docs[i + 1], i + 1);
58740                         });
58741
58742                     nextLink
58743                         .append('span')
58744                         .text(docs[i + 1].title)
58745                         .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
58746                 }
58747             }
58748
58749
58750             function drawPrevious(selection$$1) {
58751                 if (i > 0) {
58752                     var prevLink = selection$$1
58753                         .append('a')
58754                         .attr('class', 'previous')
58755                         .on('click', function() {
58756                             clickHelp(docs[i - 1], i - 1);
58757                         });
58758
58759                     prevLink
58760                         .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
58761                         .append('span')
58762                         .text(docs[i - 1].title);
58763                 }
58764             }
58765         }
58766
58767
58768         function clickWalkthrough() {
58769             select(document.body).call(uiIntro(context));
58770             setVisible(false);
58771         }
58772
58773
58774         var pane = selection$$1.append('div')
58775                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
58776             tooltipBehavior = tooltip()
58777                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58778                 .html(true)
58779                 .title(uiTooltipHtml(t('help.title'), key)),
58780             button = selection$$1.append('button')
58781                 .attr('tabindex', -1)
58782                 .on('click', toggle)
58783                 .call(svgIcon('#icon-help', 'light'))
58784                 .call(tooltipBehavior),
58785             shown = false;
58786
58787
58788         var toc = pane.append('ul')
58789             .attr('class', 'toc');
58790
58791         var menuItems = toc.selectAll('li')
58792             .data(docs)
58793             .enter()
58794             .append('li')
58795             .append('a')
58796             .html(function(d) { return d.title; })
58797             .on('click', clickHelp);
58798
58799         toc.append('li')
58800             .attr('class','walkthrough')
58801             .append('a')
58802             .text(t('splash.walkthrough'))
58803             .on('click', clickWalkthrough);
58804
58805         var content = pane.append('div')
58806             .attr('class', 'left-content');
58807
58808         var doctitle = content.append('h2')
58809             .text(t('help.title'));
58810
58811         var body = content.append('div')
58812             .attr('class', 'body');
58813
58814         var nav = content.append('div')
58815             .attr('class', 'nav');
58816
58817         clickHelp(docs[0], 0);
58818
58819         var keybinding = d3keybinding('help')
58820             .on(key, toggle)
58821             .on('B', hide)
58822             .on('F', hide);
58823
58824         select(document)
58825             .call(keybinding);
58826
58827         context.surface().on('mousedown.help-outside', hide);
58828         context.container().on('mousedown.help-outside', hide);
58829     }
58830
58831     return help;
58832 }
58833
58834 function uiInfo(context) {
58835     var key = uiCmd('⌘I'),
58836         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58837         isHidden = true;
58838
58839
58840     function info(selection$$1) {
58841
58842         function radiansToMeters(r) {
58843             // using WGS84 authalic radius (6371007.1809 m)
58844             return r * 6371007.1809;
58845         }
58846
58847         function steradiansToSqmeters(r) {
58848             // http://gis.stackexchange.com/a/124857/40446
58849             return r / (4 * Math.PI) * 510065621724000;
58850         }
58851
58852
58853         function toLineString(feature) {
58854             if (feature.type === 'LineString') return feature;
58855
58856             var result = { type: 'LineString', coordinates: [] };
58857             if (feature.type === 'Polygon') {
58858                 result.coordinates = feature.coordinates[0];
58859             } else if (feature.type === 'MultiPolygon') {
58860                 result.coordinates = feature.coordinates[0][0];
58861             }
58862
58863             return result;
58864         }
58865
58866
58867         function displayLength(m) {
58868             var d = m * (isImperial ? 3.28084 : 1),
58869                 p, unit;
58870
58871             if (isImperial) {
58872                 if (d >= 5280) {
58873                     d /= 5280;
58874                     unit = 'mi';
58875                 } else {
58876                     unit = 'ft';
58877                 }
58878             } else {
58879                 if (d >= 1000) {
58880                     d /= 1000;
58881                     unit = 'km';
58882                 } else {
58883                     unit = 'm';
58884                 }
58885             }
58886
58887             // drop unnecessary precision
58888             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
58889
58890             return String(d.toFixed(p)) + ' ' + unit;
58891         }
58892
58893
58894         function displayArea(m2) {
58895             var d = m2 * (isImperial ? 10.7639111056 : 1),
58896                 d1, d2, p1, p2, unit1, unit2;
58897
58898             if (isImperial) {
58899                 if (d >= 6969600) {     // > 0.25mi² show mi²
58900                     d1 = d / 27878400;
58901                     unit1 = 'mi²';
58902                 } else {
58903                     d1 = d;
58904                     unit1 = 'ft²';
58905                 }
58906
58907                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
58908                     d2 = d / 43560;
58909                     unit2 = 'ac';
58910                 }
58911
58912             } else {
58913                 if (d >= 250000) {    // > 0.25km² show km²
58914                     d1 = d / 1000000;
58915                     unit1 = 'km²';
58916                 } else {
58917                     d1 = d;
58918                     unit1 = 'm²';
58919                 }
58920
58921                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
58922                     d2 = d / 10000;
58923                     unit2 = 'ha';
58924                 }
58925             }
58926
58927             // drop unnecessary precision
58928             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
58929             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
58930
58931             return String(d1.toFixed(p1)) + ' ' + unit1 +
58932                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
58933         }
58934
58935
58936         function redraw() {
58937             if (isHidden) return;
58938
58939             var resolver = context.graph(),
58940                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
58941                 singular = selected.length === 1 ? selected[0] : null,
58942                 extent$$1 = geoExtent$$1(),
58943                 entity;
58944
58945             wrap.html('');
58946             wrap.append('h4')
58947                 .attr('class', 'infobox-heading fillD')
58948                 .text(singular || t('infobox.selected', { n: selected.length }));
58949
58950             if (!selected.length) return;
58951
58952             var center;
58953             for (var i = 0; i < selected.length; i++) {
58954                 entity = context.entity(selected[i]);
58955                 extent$$1._extend(entity.extent(resolver));
58956             }
58957             center = extent$$1.center();
58958
58959
58960             var list = wrap.append('ul');
58961
58962             // multiple features, just display extent center..
58963             if (!singular) {
58964                 list.append('li')
58965                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58966                 return;
58967             }
58968
58969             // single feature, display details..
58970             if (!entity) return;
58971             var geometry = entity.geometry(resolver);
58972
58973             if (geometry === 'line' || geometry === 'area') {
58974                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
58975                     feature = entity.asGeoJSON(resolver),
58976                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
58977                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
58978                     centroid = d3GeoCentroid(feature);
58979
58980                 list.append('li')
58981                     .text(t('infobox.geometry') + ': ' +
58982                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
58983
58984                 if (closed) {
58985                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
58986                     list.append('li')
58987                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
58988                 }
58989
58990                 list.append('li')
58991                     .text(lengthLabel + ': ' + displayLength(length));
58992
58993                 list.append('li')
58994                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
58995
58996
58997                 var toggle  = isImperial ? 'imperial' : 'metric';
58998                 wrap.append('a')
58999                     .text(t('infobox.' + toggle))
59000                     .attr('href', '#')
59001                     .attr('class', 'button')
59002                     .on('click', function() {
59003                         event.preventDefault();
59004                         isImperial = !isImperial;
59005                         redraw();
59006                     });
59007
59008             } else {
59009                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
59010
59011                 list.append('li')
59012                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
59013
59014                 list.append('li')
59015                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
59016             }
59017         }
59018
59019
59020         function toggle() {
59021             if (event) {
59022                 event.preventDefault();
59023             }
59024
59025             isHidden = !isHidden;
59026
59027             if (isHidden) {
59028                 wrap
59029                     .style('display', 'block')
59030                     .style('opacity', 1)
59031                     .transition()
59032                     .duration(200)
59033                     .style('opacity', 0)
59034                     .on('end', function() {
59035                         select(this).style('display', 'none');
59036                     });
59037             } else {
59038                 wrap
59039                     .style('display', 'block')
59040                     .style('opacity', 0)
59041                     .transition()
59042                     .duration(200)
59043                     .style('opacity', 1)
59044                     .on('end', function() {
59045                         redraw();
59046                     });
59047             }
59048         }
59049
59050
59051         var wrap = selection$$1.selectAll('.infobox')
59052             .data([0]);
59053
59054         wrap = wrap.enter()
59055             .append('div')
59056             .attr('class', 'infobox fillD2')
59057             .style('display', (isHidden ? 'none' : 'block'))
59058             .merge(wrap);
59059
59060         context.map()
59061             .on('drawn.info', redraw);
59062
59063         redraw();
59064
59065         var keybinding = d3keybinding('info')
59066             .on(key, toggle);
59067
59068         select(document)
59069             .call(keybinding);
59070     }
59071
59072     return info;
59073 }
59074
59075 function uiMapData(context) {
59076     var key = 'F',
59077         features = context.features().keys(),
59078         layers = context.layers(),
59079         fills = ['wireframe', 'partial', 'full'],
59080         fillDefault = context.storage('area-fill') || 'partial',
59081         fillSelected = fillDefault;
59082
59083
59084     function map_data(selection$$1) {
59085
59086         function showsFeature(d) {
59087             return context.features().enabled(d);
59088         }
59089
59090
59091         function autoHiddenFeature(d) {
59092             return context.features().autoHidden(d);
59093         }
59094
59095
59096         function clickFeature(d) {
59097             context.features().toggle(d);
59098             update();
59099         }
59100
59101
59102         function showsFill(d) {
59103             return fillSelected === d;
59104         }
59105
59106
59107         function setFill(d) {
59108             lodash.each(fills, function(opt) {
59109                 context.surface().classed('fill-' + opt, Boolean(opt === d));
59110             });
59111
59112             fillSelected = d;
59113             if (d !== 'wireframe') {
59114                 fillDefault = d;
59115                 context.storage('area-fill', d);
59116             }
59117             update();
59118         }
59119
59120
59121         function showsLayer(which) {
59122             var layer = layers.layer(which);
59123             if (layer) {
59124                 return layer.enabled();
59125             }
59126             return false;
59127         }
59128
59129
59130         function setLayer(which, enabled) {
59131             var layer = layers.layer(which);
59132             if (layer) {
59133                 layer.enabled(enabled);
59134                 update();
59135             }
59136         }
59137
59138
59139         function toggleLayer(which) {
59140             setLayer(which, !showsLayer(which));
59141         }
59142
59143
59144         function clickGpx() {
59145             toggleLayer('gpx');
59146         }
59147
59148
59149         function clickMapillaryImages() {
59150             toggleLayer('mapillary-images');
59151             if (!showsLayer('mapillary-images')) {
59152                 setLayer('mapillary-signs', false);
59153             }
59154         }
59155
59156
59157         function clickMapillarySigns() {
59158             toggleLayer('mapillary-signs');
59159         }
59160
59161
59162         function drawMapillaryItems(selection$$1) {
59163             var mapillaryImages = layers.layer('mapillary-images'),
59164                 mapillarySigns = layers.layer('mapillary-signs'),
59165                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
59166                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
59167                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
59168                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
59169
59170             var mapillaryList = selection$$1
59171                 .selectAll('.layer-list-mapillary')
59172                 .data([0]);
59173
59174             mapillaryList = mapillaryList.enter()
59175                 .append('ul')
59176                 .attr('class', 'layer-list layer-list-mapillary')
59177                 .merge(mapillaryList);
59178
59179
59180             var mapillaryImageLayerItem = mapillaryList
59181                 .selectAll('.list-item-mapillary-images')
59182                 .data(supportsMapillaryImages ? [0] : []);
59183
59184             mapillaryImageLayerItem.exit()
59185                 .remove();
59186
59187             var enterImages = mapillaryImageLayerItem.enter()
59188                 .append('li')
59189                 .attr('class', 'list-item-mapillary-images');
59190
59191             var labelImages = enterImages
59192                 .append('label')
59193                 .call(tooltip()
59194                     .title(t('mapillary_images.tooltip'))
59195                     .placement('top'));
59196
59197             labelImages
59198                 .append('input')
59199                 .attr('type', 'checkbox')
59200                 .on('change', clickMapillaryImages);
59201
59202             labelImages
59203                 .append('span')
59204                 .text(t('mapillary_images.title'));
59205
59206
59207             var mapillarySignLayerItem = mapillaryList
59208                 .selectAll('.list-item-mapillary-signs')
59209                 .data(supportsMapillarySigns ? [0] : []);
59210
59211             mapillarySignLayerItem.exit()
59212                 .remove();
59213
59214             var enterSigns = mapillarySignLayerItem.enter()
59215                 .append('li')
59216                 .attr('class', 'list-item-mapillary-signs');
59217
59218             var labelSigns = enterSigns
59219                 .append('label')
59220                 .call(tooltip()
59221                     .title(t('mapillary_signs.tooltip'))
59222                     .placement('top'));
59223
59224             labelSigns
59225                 .append('input')
59226                 .attr('type', 'checkbox')
59227                 .on('change', clickMapillarySigns);
59228
59229             labelSigns
59230                 .append('span')
59231                 .text(t('mapillary_signs.title'));
59232
59233
59234             // Updates
59235             mapillaryImageLayerItem = mapillaryImageLayerItem
59236                 .merge(enterImages);
59237
59238             mapillaryImageLayerItem
59239                 .classed('active', showsMapillaryImages)
59240                 .selectAll('input')
59241                 .property('checked', showsMapillaryImages);
59242
59243
59244             mapillarySignLayerItem = mapillarySignLayerItem
59245                 .merge(enterSigns);
59246
59247             mapillarySignLayerItem
59248                 .classed('active', showsMapillarySigns)
59249                 .selectAll('input')
59250                 .property('disabled', !showsMapillaryImages)
59251                 .property('checked', showsMapillarySigns);
59252
59253             mapillarySignLayerItem
59254                 .selectAll('label')
59255                 .classed('deemphasize', !showsMapillaryImages);
59256         }
59257
59258
59259         function drawGpxItem(selection$$1) {
59260             var gpx = layers.layer('gpx'),
59261                 hasGpx = gpx && gpx.hasGpx(),
59262                 showsGpx = hasGpx && gpx.enabled();
59263
59264             var gpxLayerItem = selection$$1
59265                 .selectAll('.layer-list-gpx')
59266                 .data(gpx ? [0] : []);
59267
59268             // Exit
59269             gpxLayerItem.exit()
59270                 .remove();
59271
59272             // Enter
59273             var enter = gpxLayerItem.enter()
59274                 .append('ul')
59275                 .attr('class', 'layer-list layer-list-gpx')
59276                 .append('li')
59277                 .classed('list-item-gpx', true);
59278
59279             enter
59280                 .append('button')
59281                 .attr('class', 'list-item-gpx-extent')
59282                 .call(tooltip()
59283                     .title(t('gpx.zoom'))
59284                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59285                 .on('click', function() {
59286                     event.preventDefault();
59287                     event.stopPropagation();
59288                     gpx.fitZoom();
59289                 })
59290                 .call(svgIcon('#icon-search'));
59291
59292             enter
59293                 .append('button')
59294                 .attr('class', 'list-item-gpx-browse')
59295                 .call(tooltip()
59296                     .title(t('gpx.browse'))
59297                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59298                 .on('click', function() {
59299                     select(document.createElement('input'))
59300                         .attr('type', 'file')
59301                         .on('change', function() {
59302                             gpx.files(event.target.files);
59303                         })
59304                         .node().click();
59305                 })
59306                 .call(svgIcon('#icon-geolocate'));
59307
59308             var labelGpx = enter
59309                 .append('label')
59310                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
59311
59312             labelGpx
59313                 .append('input')
59314                 .attr('type', 'checkbox')
59315                 .on('change', clickGpx);
59316
59317             labelGpx
59318                 .append('span')
59319                 .text(t('gpx.local_layer'));
59320
59321
59322             // Update
59323             gpxLayerItem = gpxLayerItem
59324                 .merge(enter);
59325
59326             gpxLayerItem
59327                 .classed('active', showsGpx)
59328                 .selectAll('input')
59329                 .property('disabled', !hasGpx)
59330                 .property('checked', showsGpx);
59331
59332             gpxLayerItem
59333                 .selectAll('label')
59334                 .classed('deemphasize', !hasGpx);
59335         }
59336
59337
59338         function drawList(selection$$1, data, type, name, change, active$$1) {
59339             var items = selection$$1.selectAll('li')
59340                 .data(data);
59341
59342             // Exit
59343             items.exit()
59344                 .remove();
59345
59346             // Enter
59347             var enter = items.enter()
59348                 .append('li')
59349                 .attr('class', 'layer')
59350                 .call(tooltip()
59351                     .html(true)
59352                     .title(function(d) {
59353                         var tip = t(name + '.' + d + '.tooltip'),
59354                             key = (d === 'wireframe' ? 'W' : null);
59355
59356                         if (name === 'feature' && autoHiddenFeature(d)) {
59357                             tip += '<div>' + t('map_data.autohidden') + '</div>';
59358                         }
59359                         return uiTooltipHtml(tip, key);
59360                     })
59361                     .placement('top')
59362                 );
59363
59364             var label = enter
59365                 .append('label');
59366
59367             label
59368                 .append('input')
59369                 .attr('type', type)
59370                 .attr('name', name)
59371                 .on('change', change);
59372
59373             label
59374                 .append('span')
59375                 .text(function(d) { return t(name + '.' + d + '.description'); });
59376
59377             // Update
59378             items = items
59379                 .merge(enter);
59380
59381             items
59382                 .classed('active', active$$1)
59383                 .selectAll('input')
59384                 .property('checked', active$$1)
59385                 .property('indeterminate', function(d) {
59386                     return (name === 'feature' && autoHiddenFeature(d));
59387                 });
59388         }
59389
59390
59391         function update() {
59392             dataLayerContainer.call(drawMapillaryItems);
59393             dataLayerContainer.call(drawGpxItem);
59394
59395             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
59396             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
59397         }
59398
59399
59400         function hidePanel() {
59401             setVisible(false);
59402         }
59403
59404
59405         function togglePanel() {
59406             if (event) event.preventDefault();
59407             tooltipBehavior.hide(button);
59408             setVisible(!button.classed('active'));
59409         }
59410
59411
59412         function toggleWireframe() {
59413             if (event) {
59414                 event.preventDefault();
59415                 event.stopPropagation();
59416             }
59417             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
59418             context.map().pan([0,0]);  // trigger a redraw
59419         }
59420
59421
59422         function setVisible(show) {
59423             if (show !== shown) {
59424                 button.classed('active', show);
59425                 shown = show;
59426
59427                 if (show) {
59428                     update();
59429                     selection$$1.on('mousedown.map_data-inside', function() {
59430                         return event.stopPropagation();
59431                     });
59432                     content.style('display', 'block')
59433                         .style('right', '-300px')
59434                         .transition()
59435                         .duration(200)
59436                         .style('right', '0px');
59437                 } else {
59438                     content.style('display', 'block')
59439                         .style('right', '0px')
59440                         .transition()
59441                         .duration(200)
59442                         .style('right', '-300px')
59443                         .on('end', function() {
59444                             select(this).style('display', 'none');
59445                         });
59446                     selection$$1.on('mousedown.map_data-inside', null);
59447                 }
59448             }
59449         }
59450
59451
59452         var content = selection$$1
59453                 .append('div')
59454                 .attr('class', 'fillL map-overlay col3 content hide'),
59455             tooltipBehavior = tooltip()
59456                 .placement((textDirection === 'rtl') ? 'right' : 'left')
59457                 .html(true)
59458                 .title(uiTooltipHtml(t('map_data.description'), key)),
59459             button = selection$$1
59460                 .append('button')
59461                 .attr('tabindex', -1)
59462                 .on('click', togglePanel)
59463                 .call(svgIcon('#icon-data', 'light'))
59464                 .call(tooltipBehavior),
59465             shown = false;
59466
59467         content
59468             .append('h4')
59469             .text(t('map_data.title'));
59470
59471
59472         // data layers
59473         content
59474             .append('a')
59475             .text(t('map_data.data_layers'))
59476             .attr('href', '#')
59477             .classed('hide-toggle', true)
59478             .classed('expanded', true)
59479             .on('click', function() {
59480                 var exp = select(this).classed('expanded');
59481                 dataLayerContainer.style('display', exp ? 'none' : 'block');
59482                 select(this).classed('expanded', !exp);
59483                 event.preventDefault();
59484             });
59485
59486         var dataLayerContainer = content
59487             .append('div')
59488             .attr('class', 'data-data-layers')
59489             .style('display', 'block');
59490
59491
59492         // area fills
59493         content
59494             .append('a')
59495             .text(t('map_data.fill_area'))
59496             .attr('href', '#')
59497             .classed('hide-toggle', true)
59498             .classed('expanded', false)
59499             .on('click', function() {
59500                 var exp = select(this).classed('expanded');
59501                 fillContainer.style('display', exp ? 'none' : 'block');
59502                 select(this).classed('expanded', !exp);
59503                 event.preventDefault();
59504             });
59505
59506         var fillContainer = content
59507             .append('div')
59508             .attr('class', 'data-area-fills')
59509             .style('display', 'none');
59510
59511         var fillList = fillContainer
59512             .append('ul')
59513             .attr('class', 'layer-list layer-fill-list');
59514
59515
59516         // feature filters
59517         content
59518             .append('a')
59519             .text(t('map_data.map_features'))
59520             .attr('href', '#')
59521             .classed('hide-toggle', true)
59522             .classed('expanded', false)
59523             .on('click', function() {
59524                 var exp = select(this).classed('expanded');
59525                 featureContainer.style('display', exp ? 'none' : 'block');
59526                 select(this).classed('expanded', !exp);
59527                 event.preventDefault();
59528             });
59529
59530         var featureContainer = content
59531             .append('div')
59532             .attr('class', 'data-feature-filters')
59533             .style('display', 'none');
59534
59535         var featureList = featureContainer
59536             .append('ul')
59537             .attr('class', 'layer-list layer-feature-list');
59538
59539
59540         context.features()
59541             .on('change.map_data-update', update);
59542
59543         setFill(fillDefault);
59544
59545         var keybinding = d3keybinding('features')
59546             .on(key, togglePanel)
59547             .on('W', toggleWireframe)
59548             .on('B', hidePanel)
59549             .on('H', hidePanel);
59550
59551         select(document)
59552             .call(keybinding);
59553
59554         context.surface().on('mousedown.map_data-outside', hidePanel);
59555         context.container().on('mousedown.map_data-outside', hidePanel);
59556     }
59557
59558
59559     return map_data;
59560 }
59561
59562 function uiModes(context) {
59563     var modes = [
59564         modeAddPoint$$1(context),
59565         modeAddLine$$1(context),
59566         modeAddArea$$1(context)
59567     ];
59568
59569
59570     function editable() {
59571         return context.editable() && context.mode().id !== 'save';
59572     }
59573
59574
59575     return function(selection$$1) {
59576         var buttons = selection$$1.selectAll('button.add-button')
59577             .data(modes);
59578
59579         buttons = buttons.enter()
59580             .append('button')
59581             .attr('tabindex', -1)
59582             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
59583             .on('click.mode-buttons', function(mode) {
59584                 if (mode.id === context.mode().id) {
59585                     context.enter(modeBrowse(context));
59586                 } else {
59587                     context.enter(mode);
59588                 }
59589             })
59590             .call(tooltip()
59591                 .placement('bottom')
59592                 .html(true)
59593                 .title(function(mode) {
59594                     return uiTooltipHtml(mode.description, mode.key);
59595                 })
59596             );
59597
59598         context.map()
59599             .on('move.modes', lodash.debounce(update, 500));
59600
59601         context
59602             .on('enter.modes', update);
59603
59604         buttons
59605             .each(function(d) {
59606                 select(this)
59607                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
59608             });
59609
59610         buttons
59611             .append('span')
59612             .attr('class', 'label')
59613             .text(function(mode) { return mode.title; });
59614
59615         context
59616             .on('enter.editor', function(entered) {
59617                 selection$$1.selectAll('button.add-button')
59618                     .classed('active', function(mode) { return entered.button === mode.button; });
59619                 context.container()
59620                     .classed('mode-' + entered.id, true);
59621             });
59622
59623         context
59624             .on('exit.editor', function(exited) {
59625                 context.container()
59626                     .classed('mode-' + exited.id, false);
59627             });
59628
59629         var keybinding = d3keybinding('mode-buttons');
59630
59631         modes.forEach(function(m) {
59632             keybinding.on(m.key, function() {
59633                 if (editable()) context.enter(m);
59634             });
59635         });
59636
59637         select(document)
59638             .call(keybinding);
59639
59640
59641         function update() {
59642             selection$$1.selectAll('button.add-button')
59643                 .property('disabled', !editable());
59644         }
59645     };
59646 }
59647
59648 function uiRestore(context) {
59649
59650     return function(selection) {
59651         if (!context.history().lock() || !context.history().restorableChanges())
59652             return;
59653
59654         var modalSelection = uiModal(selection, true);
59655
59656         modalSelection.select('.modal')
59657             .attr('class', 'modal fillL col6');
59658
59659         var introModal = modalSelection.select('.content');
59660
59661         introModal
59662             .attr('class','cf');
59663
59664         introModal
59665             .append('div')
59666             .attr('class', 'modal-section')
59667             .append('h3')
59668             .text(t('restore.heading'));
59669
59670         introModal
59671             .append('div')
59672             .attr('class','modal-section')
59673             .append('p')
59674             .text(t('restore.description'));
59675
59676         var buttonWrap = introModal
59677             .append('div')
59678             .attr('class', 'modal-actions cf');
59679
59680         var restore = buttonWrap
59681             .append('button')
59682             .attr('class', 'restore col6')
59683             .text(t('restore.restore'))
59684             .on('click', function() {
59685                 context.history().restore();
59686                 modalSelection.remove();
59687             });
59688
59689         buttonWrap
59690             .append('button')
59691             .attr('class', 'reset col6')
59692             .text(t('restore.reset'))
59693             .on('click', function() {
59694                 context.history().clearSaved();
59695                 modalSelection.remove();
59696             });
59697
59698         restore.node().focus();
59699     };
59700 }
59701
59702 function uiSave(context) {
59703     var history = context.history(),
59704         key = uiCmd('⌘S');
59705
59706
59707     function saving() {
59708         return context.mode().id === 'save';
59709     }
59710
59711
59712     function save() {
59713         event.preventDefault();
59714         if (!context.inIntro() && !saving() && history.hasChanges()) {
59715             context.enter(modeSave$$1(context));
59716         }
59717     }
59718
59719
59720     function getBackground(numChanges) {
59721         var step;
59722         if (numChanges === 0) {
59723             return null;
59724         } else if (numChanges <= 50) {
59725             step = numChanges / 50;
59726             return rgb$1('#fff', '#ff8')(step);  // white -> yellow
59727         } else {
59728             step = Math.min((numChanges - 50) / 50, 1.0);
59729             return rgb$1('#ff8', '#f88')(step);  // yellow -> red
59730         }
59731     }
59732
59733
59734     return function(selection$$1) {
59735         var numChanges = 0;
59736
59737         function updateCount() {
59738             var _ = history.difference().summary().length;
59739             if (_ === numChanges) return;
59740             numChanges = _;
59741
59742             tooltipBehavior
59743                 .title(uiTooltipHtml(
59744                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
59745                 );
59746
59747             var background = getBackground(numChanges);
59748
59749             button
59750                 .classed('disabled', numChanges === 0)
59751                 .classed('has-count', numChanges > 0)
59752                 .style('background', background);
59753
59754             button.select('span.count')
59755                 .text(numChanges)
59756                 .style('background', background)
59757                 .style('border-color', background);
59758         }
59759
59760
59761         var tooltipBehavior = tooltip()
59762             .placement('bottom')
59763             .html(true)
59764             .title(uiTooltipHtml(t('save.no_changes'), key));
59765
59766         var button = selection$$1
59767             .append('button')
59768             .attr('class', 'save col12 disabled')
59769             .attr('tabindex', -1)
59770             .on('click', save)
59771             .call(tooltipBehavior);
59772
59773         button
59774             .call(svgIcon('#icon-save', 'pre-text'))
59775             .append('span')
59776             .attr('class', 'label')
59777             .text(t('save.title'));
59778
59779         button
59780             .append('span')
59781             .attr('class', 'count')
59782             .text('0');
59783
59784         updateCount();
59785
59786
59787         var keybinding = d3keybinding('save')
59788             .on(key, save, true);
59789
59790         select(document)
59791             .call(keybinding);
59792
59793         context.history()
59794             .on('change.save', updateCount);
59795
59796         context
59797             .on('enter.save', function() {
59798                 button.property('disabled', saving());
59799                 if (saving()) button.call(tooltipBehavior.hide);
59800             });
59801     };
59802 }
59803
59804 function uiScale(context) {
59805     var projection = context.projection,
59806         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
59807         maxLength = 180,
59808         tickHeight = 8;
59809
59810
59811     function scaleDefs(loc1, loc2) {
59812         var lat = (loc2[1] + loc1[1]) / 2,
59813             conversion = (isImperial ? 3.28084 : 1),
59814             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
59815             scale = { dist: 0, px: 0, text: '' },
59816             buckets, i, val, dLon;
59817
59818         if (isImperial) {
59819             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
59820         } else {
59821             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
59822         }
59823
59824         // determine a user-friendly endpoint for the scale
59825         for (i = 0; i < buckets.length; i++) {
59826             val = buckets[i];
59827             if (dist >= val) {
59828                 scale.dist = Math.floor(dist / val) * val;
59829                 break;
59830             } else {
59831                 scale.dist = +dist.toFixed(2);
59832             }
59833         }
59834
59835         dLon = geoMetersToLon(scale.dist / conversion, lat);
59836         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
59837
59838         if (isImperial) {
59839             if (scale.dist >= 5280) {
59840                 scale.dist /= 5280;
59841                 scale.text = String(scale.dist) + ' mi';
59842             } else {
59843                 scale.text = String(scale.dist) + ' ft';
59844             }
59845         } else {
59846             if (scale.dist >= 1000) {
59847                 scale.dist /= 1000;
59848                 scale.text = String(scale.dist) + ' km';
59849             } else {
59850                 scale.text = String(scale.dist) + ' m';
59851             }
59852         }
59853
59854         return scale;
59855     }
59856
59857
59858     function update(selection) {
59859         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
59860         var dims = context.map().dimensions(),
59861             loc1 = projection.invert([0, dims[1]]),
59862             loc2 = projection.invert([maxLength, dims[1]]),
59863             scale = scaleDefs(loc1, loc2);
59864
59865         selection.select('#scalepath')
59866             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
59867
59868         selection.select('#scaletext')
59869             .attr('x', scale.px + 8)
59870             .attr('y', tickHeight)
59871             .text(scale.text);
59872     }
59873
59874
59875     return function(selection) {
59876         function switchUnits() {
59877             isImperial = !isImperial;
59878             selection.call(update);
59879         }
59880
59881         var g = selection.append('svg')
59882             .attr('id', 'scale')
59883             .on('click', switchUnits)
59884             .append('g')
59885             .attr('transform', 'translate(10,11)');
59886
59887         g.append('path').attr('id', 'scalepath');
59888         g.append('text').attr('id', 'scaletext');
59889
59890         selection.call(update);
59891
59892         context.map().on('move.scale', function() {
59893             update(selection);
59894         });
59895     };
59896 }
59897
59898 var pair_1 = pair;
59899 function search(x, dims, r) {
59900   if (!dims) dims = 'NSEW';
59901   if (typeof x !== 'string') return { val: null, regex: r };
59902   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
59903   var m = r.exec(x);
59904   if (!m) return { val: null, regex: r };
59905   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
59906   else return {
59907     val: (((m[1]) ? parseFloat(m[1]) : 0) +
59908           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
59909           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
59910           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
59911     regex: r,
59912     raw: m[0],
59913     dim: m[4]
59914   };
59915 }
59916
59917 function pair(x, dims) {
59918   x = x.trim();
59919   var one = search(x, dims);
59920   if (one.val === null) return null;
59921   var two = search(x, dims, one.regex);
59922   if (two.val === null) return null;
59923   // null if one/two are not contiguous.
59924   if (one.raw + two.raw !== x) return null;
59925   if (one.dim) {
59926     return swapdim(one.val, two.val, one.dim);
59927   } else {
59928     return [one.val, two.val];
59929   }
59930 }
59931
59932 function swapdim(a, b, dim) {
59933   if (dim === 'N' || dim === 'S') return [a, b];
59934   if (dim === 'W' || dim === 'E') return [b, a];
59935 }
59936
59937 function uiFeatureList(context) {
59938     var geocodeResults;
59939
59940
59941     function featureList(selection$$1) {
59942         var header = selection$$1
59943             .append('div')
59944             .attr('class', 'header fillL cf');
59945
59946         header.append('h3')
59947             .text(t('inspector.feature_list'));
59948
59949         var searchWrap = selection$$1
59950             .append('div')
59951             .attr('class', 'search-header');
59952
59953         var search = searchWrap
59954             .append('input')
59955             .attr('placeholder', t('inspector.search'))
59956             .attr('type', 'search')
59957             .call(utilNoAuto)
59958             .on('keypress', keypress)
59959             .on('input', inputevent);
59960
59961         searchWrap
59962             .call(svgIcon('#icon-search', 'pre-text'));
59963
59964         var listWrap = selection$$1
59965             .append('div')
59966             .attr('class', 'inspector-body');
59967
59968         var list = listWrap
59969             .append('div')
59970             .attr('class', 'feature-list cf');
59971
59972         context
59973             .on('exit.feature-list', clearSearch);
59974         context.map()
59975             .on('drawn.feature-list', mapDrawn);
59976
59977
59978         function keypress() {
59979             var q = search.property('value'),
59980                 items = list.selectAll('.feature-list-item');
59981             if (event.keyCode === 13 && q.length && items.size()) {
59982                 click(items.datum());
59983             }
59984         }
59985
59986
59987         function inputevent() {
59988             geocodeResults = undefined;
59989             drawList();
59990         }
59991
59992
59993         function clearSearch() {
59994             search.property('value', '');
59995             drawList();
59996         }
59997
59998
59999         function mapDrawn(e) {
60000             if (e.full) {
60001                 drawList();
60002             }
60003         }
60004
60005
60006         function features() {
60007             var entities = {},
60008                 result = [],
60009                 graph = context.graph(),
60010                 q = search.property('value').toLowerCase();
60011
60012             if (!q) return result;
60013
60014             var idMatch = q.match(/^([nwr])([0-9]+)$/);
60015
60016             if (idMatch) {
60017                 result.push({
60018                     id: idMatch[0],
60019                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
60020                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
60021                     name: idMatch[2]
60022                 });
60023             }
60024
60025             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
60026
60027             if (locationMatch) {
60028                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
60029                 result.push({
60030                     id: -1,
60031                     geometry: 'point',
60032                     type: t('inspector.location'),
60033                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
60034                     location: loc
60035                 });
60036             }
60037
60038             function addEntity(entity) {
60039                 if (entity.id in entities || result.length > 200)
60040                     return;
60041
60042                 entities[entity.id] = true;
60043
60044                 var name = utilDisplayName(entity) || '';
60045                 if (name.toLowerCase().indexOf(q) >= 0) {
60046                     var matched = context.presets().match(entity, graph),
60047                         type = (matched && matched.name()) || utilDisplayType(entity.id);
60048                     result.push({
60049                         id: entity.id,
60050                         entity: entity,
60051                         geometry: context.geometry(entity.id),
60052                         type: type,
60053                         name: name
60054                     });
60055                 }
60056
60057                 graph.parentRelations(entity).forEach(function(parent) {
60058                     addEntity(parent);
60059                 });
60060             }
60061
60062             var visible = context.surface().selectAll('.point, .line, .area').nodes();
60063             for (var i = 0; i < visible.length && result.length <= 200; i++) {
60064                 addEntity(visible[i].__data__);
60065             }
60066
60067             (geocodeResults || []).forEach(function(d) {
60068                 // https://github.com/openstreetmap/iD/issues/1890
60069                 if (d.osm_type && d.osm_id) {
60070                     result.push({
60071                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
60072                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
60073                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
60074                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
60075                         name: d.display_name,
60076                         extent: new geoExtent$$1(
60077                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
60078                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
60079                     });
60080                 }
60081             });
60082
60083             return result;
60084         }
60085
60086
60087         function drawList() {
60088             var value = search.property('value'),
60089                 results = features();
60090
60091             list.classed('filtered', value.length);
60092
60093             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
60094
60095             var resultsIndicator = list.selectAll('.no-results-item')
60096                 .data([0])
60097                 .enter().append('button')
60098                 .property('disabled', true)
60099                 .attr('class', 'no-results-item')
60100                 .call(svgIcon('#icon-alert', 'pre-text'));
60101
60102             resultsIndicator.append('span')
60103                 .attr('class', 'entity-name');
60104
60105             list.selectAll('.no-results-item .entity-name')
60106                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
60107
60108             list.selectAll('.geocode-item')
60109                 .data([0])
60110                 .enter().append('button')
60111                 .attr('class', 'geocode-item')
60112                 .on('click', geocoderSearch)
60113                 .append('div')
60114                 .attr('class', 'label')
60115                 .append('span')
60116                 .attr('class', 'entity-name')
60117                 .text(t('geocoder.search'));
60118
60119             list.selectAll('.no-results-item')
60120                 .style('display', (value.length && !results.length) ? 'block' : 'none');
60121
60122             list.selectAll('.geocode-item')
60123                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
60124
60125             list.selectAll('.feature-list-item')
60126                 .data([-1])
60127                 .remove();
60128
60129             var items = list.selectAll('.feature-list-item')
60130                 .data(results, function(d) { return d.id; });
60131
60132             var enter = items.enter()
60133                 .insert('button', '.geocode-item')
60134                 .attr('class', 'feature-list-item')
60135                 .on('mouseover', mouseover)
60136                 .on('mouseout', mouseout)
60137                 .on('click', click);
60138
60139             var label = enter
60140                 .append('div')
60141                 .attr('class', 'label');
60142
60143             label.each(function(d) {
60144                 select(this)
60145                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
60146             });
60147
60148             label.append('span')
60149                 .attr('class', 'entity-type')
60150                 .text(function(d) { return d.type; });
60151
60152             label.append('span')
60153                 .attr('class', 'entity-name')
60154                 .text(function(d) { return d.name; });
60155
60156             enter.style('opacity', 0)
60157                 .transition()
60158                 .style('opacity', 1);
60159
60160             items.order();
60161
60162             items.exit()
60163                 .remove();
60164         }
60165
60166
60167         function mouseover(d) {
60168             if (d.id === -1) return;
60169
60170             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
60171                 .classed('hover', true);
60172         }
60173
60174
60175         function mouseout() {
60176             context.surface().selectAll('.hover')
60177                 .classed('hover', false);
60178         }
60179
60180
60181         function click(d) {
60182             event.preventDefault();
60183             if (d.location) {
60184                 context.map().centerZoom([d.location[1], d.location[0]], 20);
60185             }
60186             else if (d.entity) {
60187                 if (d.entity.type === 'node') {
60188                     context.map().center(d.entity.loc);
60189                 } else if (d.entity.type === 'way') {
60190                     var center = context.projection(context.map().center()),
60191                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
60192                     context.map().center(edge.loc);
60193                 }
60194                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
60195             } else {
60196                 context.zoomToEntity(d.id);
60197             }
60198         }
60199
60200
60201         function geocoderSearch() {
60202             services.geocoder.search(search.property('value'), function (err, resp) {
60203                 geocodeResults = resp || [];
60204                 drawList();
60205             });
60206         }
60207     }
60208
60209
60210     return featureList;
60211 }
60212
60213 function uiPresetIcon() {
60214     var preset, geometry;
60215
60216
60217     function presetIcon(selection$$1) {
60218         selection$$1.each(render);
60219     }
60220
60221
60222     function render() {
60223         var selection$$1 = select(this),
60224             p = preset.apply(this, arguments),
60225             geom = geometry.apply(this, arguments),
60226             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
60227             isMaki = dataFeatureIcons.indexOf(picon) !== -1;
60228
60229         function tag_classes(p) {
60230             var s = '';
60231             for (var i in p.tags) {
60232                 s += ' tag-' + i;
60233                 if (p.tags[i] !== '*') {
60234                     s += ' tag-' + i + '-' + p.tags[i];
60235                 }
60236             }
60237             return s;
60238         }
60239
60240         var fill = selection$$1.selectAll('.preset-icon-fill')
60241             .data([0]);
60242
60243         fill = fill.enter()
60244             .append('div')
60245             .merge(fill);
60246
60247         fill
60248             .attr('class', function() {
60249                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
60250             });
60251
60252         var frame = selection$$1.selectAll('.preset-icon-frame')
60253             .data([0]);
60254
60255         frame = frame.enter()
60256             .append('div')
60257             .call(svgIcon('#preset-icon-frame'))
60258             .merge(frame);
60259
60260         frame
60261             .attr('class', function() {
60262                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
60263             });
60264
60265
60266         var icon = selection$$1.selectAll('.preset-icon')
60267             .data([0]);
60268
60269         icon = icon.enter()
60270             .append('div')
60271             .attr('class', 'preset-icon')
60272             .call(svgIcon(''))
60273             .merge(icon);
60274
60275         icon
60276             .attr('class', 'preset-icon preset-icon-' +
60277                 (isMaki ? (geom === 'area' ? '24' : '28') : (geom === 'area' ? '44' : '60'))
60278             );
60279
60280         icon.selectAll('svg')
60281             .attr('class', function() {
60282                 return 'icon ' + picon + (isMaki ? '' : tag_classes(p));
60283             });
60284
60285         icon.selectAll('use')
60286             .attr('href', '#' + picon + (isMaki ? '-15' : ''));
60287     }
60288
60289
60290     presetIcon.preset = function(_) {
60291         if (!arguments.length) return preset;
60292         preset = utilFunctor(_);
60293         return presetIcon;
60294     };
60295
60296
60297     presetIcon.geometry = function(_) {
60298         if (!arguments.length) return geometry;
60299         geometry = utilFunctor(_);
60300         return presetIcon;
60301     };
60302
60303     return presetIcon;
60304 }
60305
60306 function d3combobox() {
60307     var event$$1 = dispatch('accept'),
60308         data = [],
60309         suggestions = [],
60310         minItems = 2,
60311         caseSensitive = false;
60312
60313     var fetcher = function(val, cb) {
60314         cb(data.filter(function(d) {
60315             return d.value
60316                 .toString()
60317                 .toLowerCase()
60318                 .indexOf(val.toLowerCase()) !== -1;
60319         }));
60320     };
60321
60322     var combobox = function(input, attachTo) {
60323         var idx = -1,
60324             container = select(document.body)
60325                 .selectAll('div.combobox')
60326                 .filter(function(d) { return d === input.node(); }),
60327             shown = !container.empty();
60328
60329         input
60330             .classed('combobox-input', true)
60331             .on('focus.typeahead', focus)
60332             .on('blur.typeahead', blur)
60333             .on('keydown.typeahead', keydown)
60334             .on('keyup.typeahead', keyup)
60335             .on('input.typeahead', change)
60336             .each(function() {
60337                 var parent = this.parentNode,
60338                     sibling = this.nextSibling;
60339
60340                 var caret = select(parent).selectAll('.combobox-caret')
60341                     .filter(function(d) { return d === input.node(); })
60342                     .data([input.node()]);
60343
60344                 caret = caret.enter()
60345                   .insert('div', function() { return sibling; })
60346                     .attr('class', 'combobox-caret')
60347                   .merge(caret);
60348
60349                 caret
60350                     .on('mousedown', function () {
60351                         // prevent the form element from blurring. it blurs
60352                         // on mousedown
60353                         event.stopPropagation();
60354                         event.preventDefault();
60355                         if (!shown) {
60356                             input.node().focus();
60357                             fetch('', render);
60358                         } else {
60359                             hide();
60360                         }
60361                     });
60362             });
60363
60364         function focus() {
60365             fetch(value(), render);
60366         }
60367
60368         function blur() {
60369             window.setTimeout(hide, 150);
60370         }
60371
60372         function show() {
60373             if (!shown) {
60374                 container = select(document.body)
60375                     .insert('div', ':first-child')
60376                     .datum(input.node())
60377                     .attr('class', 'combobox')
60378                     .style('position', 'absolute')
60379                     .style('display', 'block')
60380                     .style('left', '0px')
60381                     .on('mousedown', function () {
60382                         // prevent moving focus out of the text field
60383                         event.preventDefault();
60384                     });
60385
60386                 select(document.body)
60387                     .on('scroll.combobox', render, true);
60388
60389                 shown = true;
60390             }
60391         }
60392
60393         function hide() {
60394             if (shown) {
60395                 idx = -1;
60396                 container.remove();
60397
60398                 select(document.body)
60399                     .on('scroll.combobox', null);
60400
60401                 shown = false;
60402             }
60403         }
60404
60405         function keydown() {
60406            switch (event.keyCode) {
60407                // backspace, delete
60408                case 8:
60409                case 46:
60410                    input.on('input.typeahead', function() {
60411                        idx = -1;
60412                        render();
60413                        var start = input.property('selectionStart');
60414                        input.node().setSelectionRange(start, start);
60415                        input.on('input.typeahead', change);
60416                    });
60417                    break;
60418                // tab
60419                case 9:
60420                    container.selectAll('a.selected').each(function (d) {
60421                        event$$1.call('accept', this, d);
60422                    });
60423                    hide();
60424                    break;
60425                // return
60426                case 13:
60427                    event.preventDefault();
60428                    break;
60429                // up arrow
60430                case 38:
60431                    nav(-1);
60432                    event.preventDefault();
60433                    break;
60434                // down arrow
60435                case 40:
60436                    nav(+1);
60437                    event.preventDefault();
60438                    break;
60439            }
60440            event.stopPropagation();
60441         }
60442
60443         function keyup() {
60444             switch (event.keyCode) {
60445                 // escape
60446                 case 27:
60447                     hide();
60448                     break;
60449                 // return
60450                 case 13:
60451                     container.selectAll('a.selected').each(function (d) {
60452                        event$$1.call('accept', this, d);
60453                     });
60454                     hide();
60455                     break;
60456             }
60457         }
60458
60459         function change() {
60460             fetch(value(), function() {
60461                 if (input.property('selectionEnd') === input.property('value').length) {
60462                     autocomplete();
60463                 }
60464                 render();
60465             });
60466         }
60467
60468         function nav(dir) {
60469             if (!suggestions.length) return;
60470             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
60471             input.property('value', suggestions[idx].value);
60472             render();
60473             ensureVisible();
60474         }
60475
60476         function value() {
60477             var value = input.property('value'),
60478                 start = input.property('selectionStart'),
60479                 end = input.property('selectionEnd');
60480
60481             if (start && end) {
60482                 value = value.substring(0, start);
60483             }
60484
60485             return value;
60486         }
60487
60488         function fetch(v, cb) {
60489             fetcher.call(input, v, function(_) {
60490                 suggestions = _;
60491                 cb();
60492             });
60493         }
60494
60495         function autocomplete() {
60496             var v = caseSensitive ? value() : value().toLowerCase();
60497             idx = -1;
60498             if (!v) return;
60499
60500             for (var i = 0; i < suggestions.length; i++) {
60501                 var suggestion = suggestions[i].value,
60502                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
60503
60504                 if (compare.indexOf(v) === 0) {
60505                     idx = i;
60506                     input.property('value', suggestion);
60507                     input.node().setSelectionRange(v.length, suggestion.length);
60508                     return;
60509                 }
60510             }
60511         }
60512
60513         function render() {
60514             if (suggestions.length >= minItems && document.activeElement === input.node()) {
60515                 show();
60516             } else {
60517                 hide();
60518                 return;
60519             }
60520
60521             var options = container
60522                 .selectAll('a.combobox-option')
60523                 .data(suggestions, function(d) { return d.value; });
60524
60525             options.exit()
60526                 .remove();
60527
60528             options.enter()
60529                 .append('a')
60530                 .attr('class', 'combobox-option')
60531                 .text(function(d) { return d.value; })
60532                 .merge(options)
60533                 .attr('title', function(d) { return d.title; })
60534                 .classed('selected', function(d, i) { return i === idx; })
60535                 .on('mouseover', select$$1)
60536                 .on('click', accept)
60537                 .order();
60538
60539
60540             var node = attachTo ? attachTo.node() : input.node(),
60541                 rect = node.getBoundingClientRect();
60542
60543             container
60544                 .style('left', rect.left + 'px')
60545                 .style('width', rect.width + 'px')
60546                 .style('top', rect.height + rect.top + 'px');
60547         }
60548
60549         function select$$1(d, i) {
60550             idx = i;
60551             render();
60552         }
60553
60554         function ensureVisible() {
60555             var node = container.selectAll('a.selected').node();
60556             if (node) node.scrollIntoView();
60557         }
60558
60559         function accept(d) {
60560             if (!shown) return;
60561             input
60562                 .property('value', d.value)
60563                 .dispatch('change');
60564             event$$1.call('accept', this, d);
60565             hide();
60566         }
60567     };
60568
60569     combobox.fetcher = function(_) {
60570         if (!arguments.length) return fetcher;
60571         fetcher = _;
60572         return combobox;
60573     };
60574
60575     combobox.data = function(_) {
60576         if (!arguments.length) return data;
60577         data = _;
60578         return combobox;
60579     };
60580
60581     combobox.minItems = function(_) {
60582         if (!arguments.length) return minItems;
60583         minItems = _;
60584         return combobox;
60585     };
60586
60587     combobox.caseSensitive = function(_) {
60588         if (!arguments.length) return caseSensitive;
60589         caseSensitive = _;
60590         return combobox;
60591     };
60592
60593     return utilRebind(combobox, event$$1, 'on');
60594 }
60595
60596
60597 d3combobox.off = function(input) {
60598     input
60599         .on('focus.typeahead', null)
60600         .on('blur.typeahead', null)
60601         .on('keydown.typeahead', null)
60602         .on('keyup.typeahead', null)
60603         .on('input.typeahead', null)
60604         .each(function() {
60605             select(this.parentNode).selectAll('.combobox-caret')
60606                 .filter(function(d) { return d === input.node(); })
60607                 .on('mousedown', null);
60608         });
60609
60610     select(document.body)
60611         .on('scroll.combobox', null);
60612 };
60613
60614 function uiDisclosure() {
60615     var dispatch$$1 = dispatch('toggled'),
60616         title,
60617         expanded = false,
60618         content = function () {};
60619
60620
60621     var disclosure = function(selection$$1) {
60622         var hideToggle = selection$$1.selectAll('.hide-toggle')
60623             .data([0]);
60624
60625         hideToggle = hideToggle.enter()
60626             .append('a')
60627             .attr('href', '#')
60628             .attr('class', 'hide-toggle')
60629             .merge(hideToggle);
60630
60631         hideToggle
60632             .text(title)
60633             .on('click', toggle)
60634             .classed('expanded', expanded);
60635
60636
60637         var wrap = selection$$1.selectAll('div')
60638             .data([0]);
60639
60640         wrap = wrap.enter()
60641             .append('div')
60642             .merge(wrap);
60643
60644         wrap
60645             .classed('hide', !expanded)
60646             .call(content);
60647
60648
60649         function toggle() {
60650             expanded = !expanded;
60651             hideToggle.classed('expanded', expanded);
60652             wrap.call(uiToggle(expanded));
60653             dispatch$$1.call('toggled', this, expanded);
60654         }
60655     };
60656
60657
60658     disclosure.title = function(_) {
60659         if (!arguments.length) return title;
60660         title = _;
60661         return disclosure;
60662     };
60663
60664
60665     disclosure.expanded = function(_) {
60666         if (!arguments.length) return expanded;
60667         expanded = _;
60668         return disclosure;
60669     };
60670
60671
60672     disclosure.content = function(_) {
60673         if (!arguments.length) return content;
60674         content = _;
60675         return disclosure;
60676     };
60677
60678
60679     return utilRebind(disclosure, dispatch$$1, 'on');
60680 }
60681
60682 function uiRawMemberEditor(context) {
60683     var id,
60684         taginfo = services.taginfo;
60685
60686
60687     function selectMember(d) {
60688         event.preventDefault();
60689         context.enter(modeSelect(context, [d.id]).suppressMenu(true));
60690     }
60691
60692
60693     function changeRole(d) {
60694         var role = select(this).property('value');
60695         var member = { id: d.id, type: d.type, role: role };
60696         context.perform(
60697             actionChangeMember(d.relation.id, member, d.index),
60698             t('operations.change_role.annotation')
60699         );
60700     }
60701
60702
60703     function deleteMember(d) {
60704         context.perform(
60705             actionDeleteMember(d.relation.id, d.index),
60706             t('operations.delete_member.annotation')
60707         );
60708
60709         if (!context.hasEntity(d.relation.id)) {
60710             context.enter(modeBrowse(context));
60711         }
60712     }
60713
60714
60715     function rawMemberEditor(selection$$1) {
60716         var entity = context.entity(id),
60717             memberships = [];
60718
60719         entity.members.forEach(function(member, index) {
60720             memberships.push({
60721                 index: index,
60722                 id: member.id,
60723                 type: member.type,
60724                 role: member.role,
60725                 relation: entity,
60726                 member: context.hasEntity(member.id)
60727             });
60728         });
60729
60730         selection$$1.call(uiDisclosure()
60731             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
60732             .expanded(true)
60733             .on('toggled', toggled)
60734             .content(content)
60735         );
60736
60737
60738         function toggled(expanded) {
60739             if (expanded) {
60740                 selection$$1.node().parentNode.scrollTop += 200;
60741             }
60742         }
60743
60744
60745         function content(wrap) {
60746             var list = wrap.selectAll('.member-list')
60747                 .data([0]);
60748
60749             list = list.enter()
60750                 .append('ul')
60751                 .attr('class', 'member-list')
60752                 .merge(list);
60753
60754
60755             var items = list.selectAll('li')
60756                 .data(memberships, function(d) {
60757                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
60758                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
60759                 });
60760
60761             items.exit()
60762                 .each(unbind)
60763                 .remove();
60764
60765             var enter = items.enter()
60766                 .append('li')
60767                 .attr('class', 'member-row form-field')
60768                 .classed('member-incomplete', function(d) { return !d.member; });
60769
60770             enter
60771                 .each(function(d) {
60772                     if (d.member) {
60773                         var label = select(this).append('label')
60774                             .attr('class', 'form-label')
60775                             .append('a')
60776                             .attr('href', '#')
60777                             .on('click', selectMember);
60778
60779                         label.append('span')
60780                             .attr('class', 'member-entity-type')
60781                             .text(function(d) {
60782                                 var matched = context.presets().match(d.member, context.graph());
60783                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
60784                             });
60785
60786                         label.append('span')
60787                             .attr('class', 'member-entity-name')
60788                             .text(function(d) { return utilDisplayName(d.member); });
60789
60790                     } else {
60791                         select(this).append('label')
60792                             .attr('class', 'form-label')
60793                             .text(t('inspector.incomplete', { id: d.id }));
60794                     }
60795                 });
60796
60797             enter
60798                 .append('input')
60799                 .attr('class', 'member-role')
60800                 .property('type', 'text')
60801                 .attr('maxlength', 255)
60802                 .attr('placeholder', t('inspector.role'))
60803                 .call(utilNoAuto)
60804                 .property('value', function(d) { return d.role; })
60805                 .on('change', changeRole);
60806
60807             enter
60808                 .append('button')
60809                 .attr('tabindex', -1)
60810                 .attr('class', 'remove button-input-action member-delete minor')
60811                 .on('click', deleteMember)
60812                 .call(svgIcon('#operation-delete'));
60813
60814             if (taginfo) {
60815                 enter.each(bindTypeahead);
60816             }
60817
60818
60819             function bindTypeahead(d) {
60820                 var row = select(this),
60821                     role = row.selectAll('input.member-role');
60822
60823                 function sort(value, data) {
60824                     var sameletter = [],
60825                         other = [];
60826                     for (var i = 0; i < data.length; i++) {
60827                         if (data[i].value.substring(0, value.length) === value) {
60828                             sameletter.push(data[i]);
60829                         } else {
60830                             other.push(data[i]);
60831                         }
60832                     }
60833                     return sameletter.concat(other);
60834                 }
60835
60836                 role.call(d3combobox()
60837                     .fetcher(function(role, callback) {
60838                         var rtype = entity.tags.type;
60839                         taginfo.roles({
60840                             debounce: true,
60841                             rtype: rtype || '',
60842                             geometry: context.geometry(d.member.id),
60843                             query: role
60844                         }, function(err, data) {
60845                             if (!err) callback(sort(role, data));
60846                         });
60847                     }));
60848             }
60849
60850
60851             function unbind() {
60852                 var row = select(this);
60853
60854                 row.selectAll('input.member-role')
60855                     .call(d3combobox.off);
60856             }
60857         }
60858     }
60859
60860
60861     rawMemberEditor.entityID = function(_) {
60862         if (!arguments.length) return id;
60863         id = _;
60864         return rawMemberEditor;
60865     };
60866
60867
60868     return rawMemberEditor;
60869 }
60870
60871 function uiRawMembershipEditor(context) {
60872     var taginfo = services.taginfo,
60873         id, showBlank;
60874
60875
60876     function selectRelation(d) {
60877         event.preventDefault();
60878         context.enter(modeSelect(context, [d.relation.id]).suppressMenu(true));
60879     }
60880
60881
60882     function changeRole(d) {
60883         var role = select(this).property('value');
60884         context.perform(
60885             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
60886             t('operations.change_role.annotation')
60887         );
60888     }
60889
60890
60891     function addMembership(d, role) {
60892         showBlank = false;
60893
60894         if (d.relation) {
60895             context.perform(
60896                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
60897                 t('operations.add_member.annotation')
60898             );
60899
60900         } else {
60901             var relation = osmRelation();
60902             context.perform(
60903                 actionAddEntity(relation),
60904                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
60905                 t('operations.add.annotation.relation')
60906             );
60907
60908             context.enter(modeSelect(context, [relation.id]).suppressMenu(true));
60909         }
60910     }
60911
60912
60913     function deleteMembership(d) {
60914         context.perform(
60915             actionDeleteMember(d.relation.id, d.index),
60916             t('operations.delete_member.annotation')
60917         );
60918     }
60919
60920
60921     function relations(q) {
60922         var newRelation = {
60923                 relation: null,
60924                 value: t('inspector.new_relation')
60925             },
60926             result = [],
60927             graph = context.graph();
60928
60929         context.intersects(context.extent()).forEach(function(entity) {
60930             if (entity.type !== 'relation' || entity.id === id)
60931                 return;
60932
60933             var matched = context.presets().match(entity, graph),
60934                 presetName = (matched && matched.name()) || t('inspector.relation'),
60935                 entityName = utilDisplayName(entity) || '';
60936
60937             var value = presetName + ' ' + entityName;
60938             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
60939                 return;
60940
60941             result.push({
60942                 relation: entity,
60943                 value: value
60944             });
60945         });
60946
60947         result.sort(function(a, b) {
60948             return osmRelation.creationOrder(a.relation, b.relation);
60949         });
60950
60951         // Dedupe identical names by appending relation id - see #2891
60952         var dupeGroups = lodash(result)
60953             .groupBy('value')
60954             .filter(function(v) { return v.length > 1; })
60955             .value();
60956
60957         dupeGroups.forEach(function(group) {
60958             group.forEach(function(obj) {
60959                 obj.value += ' ' + obj.relation.id;
60960             });
60961         });
60962
60963         result.unshift(newRelation);
60964         return result;
60965     }
60966
60967
60968     function rawMembershipEditor(selection$$1) {
60969         var entity = context.entity(id),
60970             memberships = [];
60971
60972         context.graph().parentRelations(entity).forEach(function(relation) {
60973             relation.members.forEach(function(member, index) {
60974                 if (member.id === entity.id) {
60975                     memberships.push({ relation: relation, member: member, index: index });
60976                 }
60977             });
60978         });
60979
60980         selection$$1.call(uiDisclosure()
60981             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
60982             .expanded(true)
60983             .on('toggled', toggled)
60984             .content(content)
60985         );
60986
60987
60988         function toggled(expanded) {
60989             if (expanded) {
60990                 selection$$1.node().parentNode.scrollTop += 200;
60991             }
60992         }
60993
60994
60995         function content(wrap) {
60996             var list = wrap.selectAll('.member-list')
60997                 .data([0]);
60998
60999             list = list.enter()
61000                 .append('ul')
61001                 .attr('class', 'member-list')
61002                 .merge(list);
61003
61004
61005             var items = list.selectAll('li.member-row-normal')
61006                 .data(memberships, function(d) {
61007                     return osmEntity$$1.key(d.relation) + ',' + d.index;
61008                 });
61009
61010             items.exit()
61011                 .each(unbind)
61012                 .remove();
61013
61014             var enter = items.enter()
61015                 .append('li')
61016                 .attr('class', 'member-row member-row-normal form-field');
61017
61018             var label = enter
61019                 .append('label')
61020                 .attr('class', 'form-label')
61021                 .append('a')
61022                 .attr('href', '#')
61023                 .on('click', selectRelation);
61024
61025             label
61026                 .append('span')
61027                 .attr('class', 'member-entity-type')
61028                 .text(function(d) {
61029                     var matched = context.presets().match(d.relation, context.graph());
61030                     return (matched && matched.name()) || t('inspector.relation');
61031                 });
61032
61033             label
61034                 .append('span')
61035                 .attr('class', 'member-entity-name')
61036                 .text(function(d) { return utilDisplayName(d.relation); });
61037
61038             enter
61039                 .append('input')
61040                 .attr('class', 'member-role')
61041                 .property('type', 'text')
61042                 .attr('maxlength', 255)
61043                 .attr('placeholder', t('inspector.role'))
61044                 .call(utilNoAuto)
61045                 .property('value', function(d) { return d.member.role; })
61046                 .on('change', changeRole);
61047
61048             enter
61049                 .append('button')
61050                 .attr('tabindex', -1)
61051                 .attr('class', 'remove button-input-action member-delete minor')
61052                 .on('click', deleteMembership)
61053                 .call(svgIcon('#operation-delete'));
61054
61055             if (taginfo) {
61056                 enter.each(bindTypeahead);
61057             }
61058
61059
61060             var newrow = list.selectAll('.member-row-new')
61061                 .data(showBlank ? [0] : []);
61062
61063             newrow.exit()
61064                 .remove();
61065
61066             enter = newrow.enter()
61067                 .append('li')
61068                 .attr('class', 'member-row member-row-new form-field');
61069
61070             enter
61071                 .append('input')
61072                 .attr('type', 'text')
61073                 .attr('class', 'member-entity-input')
61074                 .call(utilNoAuto);
61075
61076             enter
61077                 .append('input')
61078                 .attr('class', 'member-role')
61079                 .property('type', 'text')
61080                 .attr('maxlength', 255)
61081                 .attr('placeholder', t('inspector.role'))
61082                 .call(utilNoAuto)
61083                 .on('change', changeRole);
61084
61085             enter
61086                 .append('button')
61087                 .attr('tabindex', -1)
61088                 .attr('class', 'remove button-input-action member-delete minor')
61089                 .on('click', deleteMembership)
61090                 .call(svgIcon('#operation-delete'));
61091
61092             newrow = newrow
61093                 .merge(enter);
61094
61095             newrow.selectAll('.member-entity-input')
61096                 .call(d3combobox()
61097                     .minItems(1)
61098                     .fetcher(function(value, callback) { callback(relations(value)); })
61099                     .on('accept', onAccept)
61100                 );
61101
61102
61103             var addrel = wrap.selectAll('.add-relation')
61104                 .data([0]);
61105
61106             addrel = addrel.enter()
61107                 .append('button')
61108                 .attr('class', 'add-relation')
61109                 .merge(addrel);
61110
61111             addrel
61112                 .call(svgIcon('#icon-plus', 'light'))
61113                 .on('click', function() {
61114                     showBlank = true;
61115                     content(wrap);
61116                     list.selectAll('.member-entity-input').node().focus();
61117                 });
61118
61119
61120             function onAccept(d) {
61121                 var role = list.selectAll('.member-row-new .member-role').property('value');
61122                 addMembership(d, role);
61123             }
61124
61125
61126             function bindTypeahead(d) {
61127                 var row = select(this),
61128                     role = row.selectAll('input.member-role');
61129
61130                 function sort(value, data) {
61131                     var sameletter = [],
61132                         other = [];
61133                     for (var i = 0; i < data.length; i++) {
61134                         if (data[i].value.substring(0, value.length) === value) {
61135                             sameletter.push(data[i]);
61136                         } else {
61137                             other.push(data[i]);
61138                         }
61139                     }
61140                     return sameletter.concat(other);
61141                 }
61142
61143                 role.call(d3combobox()
61144                     .fetcher(function(role, callback) {
61145                         var rtype = d.relation.tags.type;
61146                         taginfo.roles({
61147                             debounce: true,
61148                             rtype: rtype || '',
61149                             geometry: context.geometry(id),
61150                             query: role
61151                         }, function(err, data) {
61152                             if (!err) callback(sort(role, data));
61153                         });
61154                     }));
61155             }
61156
61157
61158             function unbind() {
61159                 var row = select(this);
61160
61161                 row.selectAll('input.member-role')
61162                     .call(d3combobox.off);
61163             }
61164         }
61165     }
61166
61167
61168     rawMembershipEditor.entityID = function(_) {
61169         if (!arguments.length) return id;
61170         id = _;
61171         return rawMembershipEditor;
61172     };
61173
61174
61175     return rawMembershipEditor;
61176 }
61177
61178 function uiTagReference(tag) {
61179     var taginfo = services.taginfo,
61180         tagReference = {},
61181         button,
61182         body,
61183         loaded,
61184         showing;
61185
61186
61187     function findLocal(data) {
61188         var locale = utilDetect().locale.toLowerCase(),
61189             localized;
61190
61191         if (locale !== 'pt-br') {  // see #3776, prefer 'pt' over 'pt-br'
61192             localized = lodash.find(data, function(d) {
61193                 return d.lang.toLowerCase() === locale;
61194             });
61195             if (localized) return localized;
61196         }
61197
61198         // try the non-regional version of a language, like
61199         // 'en' if the language is 'en-US'
61200         if (locale.indexOf('-') !== -1) {
61201             var first = locale.split('-')[0];
61202             localized = lodash.find(data, function(d) {
61203                 return d.lang.toLowerCase() === first;
61204             });
61205             if (localized) return localized;
61206         }
61207
61208         // finally fall back to english
61209         return lodash.find(data, function(d) {
61210             return d.lang.toLowerCase() === 'en';
61211         });
61212     }
61213
61214
61215     function load(param) {
61216         if (!taginfo) return;
61217
61218         button.classed('tag-reference-loading', true);
61219
61220         taginfo.docs(param, function show(err, data) {
61221             var docs;
61222             if (!err && data) {
61223                 docs = findLocal(data);
61224             }
61225
61226             body.html('');
61227
61228
61229             if (!docs || !docs.title) {
61230                 if (param.hasOwnProperty('value')) {
61231                     load(lodash.omit(param, 'value'));   // retry with key only
61232                 } else {
61233                     body.append('p').text(t('inspector.no_documentation_key'));
61234                     done();
61235                 }
61236                 return;
61237             }
61238
61239
61240             if (docs.image && docs.image.thumb_url_prefix) {
61241                 body
61242                     .append('img')
61243                     .attr('class', 'wiki-image')
61244                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
61245                     .on('load', function() { done(); })
61246                     .on('error', function() { select(this).remove(); done(); });
61247             } else {
61248                 done();
61249             }
61250
61251             body
61252                 .append('p')
61253                 .text(docs.description || t('inspector.documentation_redirect'));
61254
61255             body
61256                 .append('a')
61257                 .attr('target', '_blank')
61258                 .attr('tabindex', -1)
61259                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
61260                 .call(svgIcon('#icon-out-link', 'inline'))
61261                 .append('span')
61262                 .text(t('inspector.reference'));
61263         });
61264     }
61265
61266
61267     function done() {
61268         loaded = true;
61269
61270         button.classed('tag-reference-loading', false);
61271
61272         body.transition()
61273             .duration(200)
61274             .style('max-height', '200px')
61275             .style('opacity', '1');
61276
61277         showing = true;
61278     }
61279
61280
61281     function hide(selection$$1) {
61282         selection$$1 = selection$$1 || body.transition().duration(200);
61283
61284         selection$$1
61285             .style('max-height', '0px')
61286             .style('opacity', '0');
61287
61288         showing = false;
61289     }
61290
61291
61292     tagReference.button = function(selection$$1) {
61293         button = selection$$1.selectAll('.tag-reference-button')
61294             .data([0]);
61295
61296         button = button.enter()
61297             .append('button')
61298             .attr('class', 'tag-reference-button')
61299             .attr('tabindex', -1)
61300             .call(svgIcon('#icon-inspect'))
61301             .merge(button);
61302
61303         button
61304             .on('click', function () {
61305                 event.stopPropagation();
61306                 event.preventDefault();
61307                 if (showing) {
61308                     hide();
61309                 } else if (loaded) {
61310                     done();
61311                 } else {
61312                     load(tag);
61313                 }
61314             });
61315     };
61316
61317
61318     tagReference.body = function(selection$$1) {
61319         body = selection$$1.selectAll('.tag-reference-body')
61320             .data([0]);
61321
61322         body = body.enter()
61323             .append('div')
61324             .attr('class', 'tag-reference-body cf')
61325             .style('max-height', '0')
61326             .style('opacity', '0')
61327             .merge(body);
61328
61329         if (showing === false) {
61330             hide(body);
61331         }
61332     };
61333
61334
61335     tagReference.showing = function(_) {
61336         if (!arguments.length) return showing;
61337         showing = _;
61338         return tagReference;
61339     };
61340
61341
61342     return tagReference;
61343 }
61344
61345 function uiRawTagEditor(context) {
61346     var taginfo = services.taginfo,
61347         dispatch$$1 = dispatch('change'),
61348         showBlank = false,
61349         state,
61350         preset,
61351         tags,
61352         id;
61353
61354
61355     function rawTagEditor(selection$$1) {
61356         var count = Object.keys(tags).filter(function(d) { return d; }).length;
61357
61358         selection$$1.call(uiDisclosure()
61359             .title(t('inspector.all_tags') + ' (' + count + ')')
61360             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
61361             .on('toggled', toggled)
61362             .content(content));
61363
61364         function toggled(expanded) {
61365             context.storage('raw_tag_editor.expanded', expanded);
61366             if (expanded) {
61367                 selection$$1.node().parentNode.scrollTop += 200;
61368             }
61369         }
61370     }
61371
61372
61373     function content(wrap) {
61374         var entries$$1 = entries(tags);
61375
61376         if (!entries$$1.length || showBlank) {
61377             showBlank = false;
61378             entries$$1.push({key: '', value: ''});
61379         }
61380
61381         var list = wrap.selectAll('.tag-list')
61382             .data([0]);
61383
61384         list = list.enter()
61385             .append('ul')
61386             .attr('class', 'tag-list')
61387             .merge(list);
61388
61389         var newTag = wrap.selectAll('.add-tag')
61390             .data([0]);
61391
61392         newTag.enter()
61393             .append('button')
61394             .attr('class', 'add-tag')
61395             .on('click', addTag)
61396             .call(svgIcon('#icon-plus', 'light'));
61397
61398
61399         var items = list.selectAll('.tag-row')
61400             .data(entries$$1, function(d) { return d.key; });
61401
61402         items.exit()
61403             .each(unbind)
61404             .remove();
61405
61406         // Enter
61407
61408         var enter = items.enter()
61409             .append('li')
61410             .attr('class', 'tag-row cf');
61411
61412         enter
61413             .append('div')
61414             .attr('class', 'key-wrap')
61415             .append('input')
61416             .property('type', 'text')
61417             .attr('class', 'key')
61418             .attr('maxlength', 255)
61419             .call(utilNoAuto)
61420             .on('blur', keyChange)
61421             .on('change', keyChange);
61422
61423         enter
61424             .append('div')
61425             .attr('class', 'input-wrap-position')
61426             .append('input')
61427             .property('type', 'text')
61428             .attr('class', 'value')
61429             .attr('maxlength', 255)
61430             .call(utilNoAuto)
61431             .on('blur', valueChange)
61432             .on('change', valueChange)
61433             .on('keydown.push-more', pushMore);
61434
61435         enter
61436             .append('button')
61437             .attr('tabindex', -1)
61438             .attr('class', 'remove minor')
61439             .call(svgIcon('#operation-delete'));
61440
61441
61442         // Update
61443
61444         items = items
61445             .merge(enter)
61446             .sort(function(a, b) {
61447                 return (a.key === '') ? 1
61448                     : (b.key === '') ? -1
61449                     : ascending(a.key, b.key);
61450             });
61451
61452         items
61453             .each(function(tag) {
61454                 var row = select(this),
61455                     key = row.select('input.key'),      // propagate bound data to child
61456                     value = row.select('input.value');  // propagate bound data to child
61457
61458                 if (taginfo) {
61459                     bindTypeahead(key, value);
61460                 }
61461
61462                 var isRelation = (context.entity(id).type === 'relation'),
61463                     reference;
61464
61465                 if (isRelation && tag.key === 'type') {
61466                     reference = uiTagReference({ rtype: tag.value }, context);
61467                 } else {
61468                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
61469                 }
61470
61471                 if (state === 'hover') {
61472                     reference.showing(false);
61473                 }
61474
61475                 row
61476                     .call(reference.button)
61477                     .call(reference.body);
61478             });
61479
61480         items.selectAll('input.key')
61481             .attr('title', function(d) { return d.key; })
61482             .call(utilGetSetValue, function(d) { return d.key; });
61483
61484         items.selectAll('input.value')
61485             .attr('title', function(d) { return d.value; })
61486             .call(utilGetSetValue, function(d) { return d.value; });
61487
61488         items.selectAll('button.remove')
61489             .on('click', removeTag);
61490
61491
61492         function pushMore() {
61493             if (event.keyCode === 9 && !event.shiftKey &&
61494                 list.selectAll('li:last-child input.value').node() === this) {
61495                 addTag();
61496             }
61497         }
61498
61499
61500         function bindTypeahead(key, value) {
61501
61502             function sort(value, data) {
61503                 var sameletter = [],
61504                     other = [];
61505                 for (var i = 0; i < data.length; i++) {
61506                     if (data[i].value.substring(0, value.length) === value) {
61507                         sameletter.push(data[i]);
61508                     } else {
61509                         other.push(data[i]);
61510                     }
61511                 }
61512                 return sameletter.concat(other);
61513             }
61514
61515             key.call(d3combobox()
61516                 .fetcher(function(value, callback) {
61517                     taginfo.keys({
61518                         debounce: true,
61519                         geometry: context.geometry(id),
61520                         query: value
61521                     }, function(err, data) {
61522                         if (!err) callback(sort(value, data));
61523                     });
61524                 }));
61525
61526             value.call(d3combobox()
61527                 .fetcher(function(value, callback) {
61528                     taginfo.values({
61529                         debounce: true,
61530                         key: utilGetSetValue(key),
61531                         geometry: context.geometry(id),
61532                         query: value
61533                     }, function(err, data) {
61534                         if (!err) callback(sort(value, data));
61535                     });
61536                 }));
61537         }
61538
61539
61540         function unbind() {
61541             var row = select(this);
61542
61543             row.selectAll('input.key')
61544                 .call(d3combobox.off);
61545
61546             row.selectAll('input.value')
61547                 .call(d3combobox.off);
61548         }
61549
61550
61551         function keyChange(d) {
61552             var kOld = d.key,
61553                 kNew = this.value.trim(),
61554                 tag = {};
61555
61556             if (kNew && kNew !== kOld) {
61557                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
61558                     base = match[1],
61559                     suffix = +(match[2] || 1);
61560                 while (tags[kNew]) {  // rename key if already in use
61561                     kNew = base + '_' + suffix++;
61562                 }
61563             }
61564             tag[kOld] = undefined;
61565             tag[kNew] = d.value;
61566             d.key = kNew; // Maintain DOM identity through the subsequent update.
61567             this.value = kNew;
61568             dispatch$$1.call('change', this, tag);
61569         }
61570
61571
61572         function valueChange(d) {
61573             var tag = {};
61574             tag[d.key] = this.value;
61575             dispatch$$1.call('change', this, tag);
61576         }
61577
61578
61579         function removeTag(d) {
61580             var tag = {};
61581             tag[d.key] = undefined;
61582             dispatch$$1.call('change', this, tag);
61583             select(this.parentNode).remove();
61584         }
61585
61586
61587         function addTag() {
61588             // Wrapped in a setTimeout in case it's being called from a blur
61589             // handler. Without the setTimeout, the call to `content` would
61590             // wipe out the pending value change.
61591             setTimeout(function() {
61592                 showBlank = true;
61593                 content(wrap);
61594                 list.selectAll('li:last-child input.key').node().focus();
61595             }, 0);
61596         }
61597     }
61598
61599
61600     rawTagEditor.state = function(_) {
61601         if (!arguments.length) return state;
61602         state = _;
61603         return rawTagEditor;
61604     };
61605
61606
61607     rawTagEditor.preset = function(_) {
61608         if (!arguments.length) return preset;
61609         preset = _;
61610         return rawTagEditor;
61611     };
61612
61613
61614     rawTagEditor.tags = function(_) {
61615         if (!arguments.length) return tags;
61616         tags = _;
61617         return rawTagEditor;
61618     };
61619
61620
61621     rawTagEditor.entityID = function(_) {
61622         if (!arguments.length) return id;
61623         id = _;
61624         return rawTagEditor;
61625     };
61626
61627
61628     return utilRebind(rawTagEditor, dispatch$$1, 'on');
61629 }
61630
61631 function uiFieldCheck(field) {
61632     var dispatch$$1 = dispatch('change'),
61633         options = field.strings && field.strings.options,
61634         values$$1 = [],
61635         texts = [],
61636         input = select(null),
61637         text$$1 = select(null),
61638         label = select(null),
61639         entity, value;
61640
61641     if (options) {
61642         for (var k in options) {
61643             values$$1.push(k === 'undefined' ? undefined : k);
61644             texts.push(field.t('options.' + k, { 'default': options[k] }));
61645         }
61646     } else {
61647         values$$1 = [undefined, 'yes'];
61648         texts = [t('inspector.unknown'), t('inspector.check.yes')];
61649         if (field.type === 'check') {
61650             values$$1.push('no');
61651             texts.push(t('inspector.check.no'));
61652         }
61653     }
61654
61655
61656     var check = function(selection$$1) {
61657         // hack: pretend oneway field is a oneway_yes field
61658         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
61659         if (field.id === 'oneway') {
61660             for (var key in entity.tags) {
61661                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
61662                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
61663                     break;
61664                 }
61665             }
61666         }
61667
61668         selection$$1.classed('checkselect', 'true');
61669
61670         label = selection$$1.selectAll('.preset-input-wrap')
61671             .data([0]);
61672
61673         var enter = label.enter()
61674             .append('label')
61675             .attr('class', 'preset-input-wrap');
61676
61677         enter
61678             .append('input')
61679             .property('indeterminate', field.type === 'check')
61680             .attr('type', 'checkbox')
61681             .attr('id', 'preset-input-' + field.id);
61682
61683         enter
61684             .append('span')
61685             .text(texts[0])
61686             .attr('class', 'value');
61687
61688         label = label.merge(enter);
61689         input = label.selectAll('input');
61690         text$$1 = label.selectAll('span.value');
61691
61692         input
61693             .on('click', function() {
61694                 var t$$1 = {};
61695                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
61696                 dispatch$$1.call('change', this, t$$1);
61697                 event.stopPropagation();
61698             });
61699     };
61700
61701
61702     check.entity = function(_) {
61703         if (!arguments.length) return entity;
61704         entity = _;
61705         return check;
61706     };
61707
61708
61709     check.tags = function(tags) {
61710         value = tags[field.key];
61711         input.property('indeterminate', field.type === 'check' && !value);
61712         input.property('checked', value === 'yes');
61713         text$$1.text(texts[values$$1.indexOf(value)]);
61714         label.classed('set', !!value);
61715     };
61716
61717
61718     check.focus = function() {
61719         input.node().focus();
61720     };
61721
61722     return utilRebind(check, dispatch$$1, 'on');
61723 }
61724
61725 function uiFieldCombo(field, context) {
61726     var dispatch$$1 = dispatch('change'),
61727         nominatim = services.geocoder,
61728         taginfo = services.taginfo,
61729         isMulti = (field.type === 'multiCombo'),
61730         isNetwork = (field.type === 'networkCombo'),
61731         optstrings = field.strings && field.strings.options,
61732         optarray = field.options,
61733         snake_case = (field.snake_case || (field.snake_case === undefined)),
61734         combobox = d3combobox().minItems(isMulti ? 1 : 2),
61735         comboData = [],
61736         multiData = [],
61737         container,
61738         input,
61739         entity,
61740         country;
61741
61742     // ensure multiCombo field.key ends with a ':'
61743     if (isMulti && field.key.match(/:$/) === null) {
61744         field.key += ':';
61745     }
61746
61747
61748     function snake(s) {
61749         return s.replace(/\s+/g, '_');
61750     }
61751
61752     function unsnake(s) {
61753         return s.replace(/_+/g, ' ');
61754     }
61755
61756     function clean(s) {
61757         return s.split(';')
61758             .map(function(s) { return s.trim(); })
61759             .join(';');
61760     }
61761
61762
61763     // returns the tag value for a display value
61764     // (for multiCombo, dval should be the key suffix, not the entire key)
61765     function tagValue(dval) {
61766         dval = clean(dval || '');
61767
61768         if (optstrings) {
61769             var match = lodash.find(comboData, function(o) {
61770                 return o.key && clean(o.value) === dval;
61771             });
61772             if (match) {
61773                 return match.key;
61774             }
61775         }
61776
61777         if (field.type === 'typeCombo' && !dval) {
61778             return 'yes';
61779         }
61780
61781         return (snake_case ? snake(dval) : dval) || undefined;
61782     }
61783
61784
61785     // returns the display value for a tag value
61786     // (for multiCombo, tval should be the key suffix, not the entire key)
61787     function displayValue(tval) {
61788         tval = tval || '';
61789
61790         if (optstrings) {
61791             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
61792             if (match) {
61793                 return match.value;
61794             }
61795         }
61796
61797         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
61798             return '';
61799         }
61800
61801         return snake_case ? unsnake(tval) : tval;
61802     }
61803
61804
61805     function objectDifference(a, b) {
61806         return lodash.reject(a, function(d1) {
61807             return lodash.some(b, function(d2) { return d1.value === d2.value; });
61808         });
61809     }
61810
61811
61812     function initCombo(selection$$1, attachTo) {
61813         if (optstrings) {
61814             selection$$1.attr('readonly', 'readonly');
61815             selection$$1.call(combobox, attachTo);
61816             setStaticValues(setPlaceholder);
61817
61818         } else if (optarray) {
61819             selection$$1.call(combobox, attachTo);
61820             setStaticValues(setPlaceholder);
61821
61822         } else if (taginfo) {
61823             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
61824             setTaginfoValues('', setPlaceholder);
61825         }
61826     }
61827
61828
61829     function setStaticValues(callback) {
61830         if (!(optstrings || optarray)) return;
61831
61832         if (optstrings) {
61833             comboData = Object.keys(optstrings).map(function(k) {
61834                 var v = field.t('options.' + k, { 'default': optstrings[k] });
61835                 return {
61836                     key: k,
61837                     value: v,
61838                     title: v
61839                 };
61840             });
61841
61842         } else if (optarray) {
61843             comboData = optarray.map(function(k) {
61844                 var v = snake_case ? unsnake(k) : k;
61845                 return {
61846                     key: k,
61847                     value: v,
61848                     title: v
61849                 };
61850             });
61851         }
61852
61853         combobox.data(objectDifference(comboData, multiData));
61854         if (callback) callback(comboData);
61855     }
61856
61857
61858     function setTaginfoValues(q, callback) {
61859         var fn = isMulti ? 'multikeys' : 'values';
61860         var query = (isMulti ? field.key : '') + q;
61861         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
61862         if (hasCountryPrefix) {
61863             query = country + ':';
61864         }
61865         taginfo[fn]({
61866             debounce: true,
61867             key: field.key,
61868             geometry: context.geometry(entity.id),
61869             query: query
61870         }, function(err, data) {
61871             if (err) return;
61872             if (hasCountryPrefix) {
61873                 data = lodash.filter(data, function(d) {
61874                     return d.value.toLowerCase().indexOf(country + ':') === 0;
61875                 });
61876             }
61877             comboData = lodash.map(data, function(d) {
61878                 var k = d.value;
61879                 if (isMulti) k = k.replace(field.key, '');
61880                 var v = snake_case ? unsnake(k) : k;
61881                 return {
61882                     key: k,
61883                     value: v,
61884                     title: isMulti ? v : d.title
61885                 };
61886             });
61887             comboData = objectDifference(comboData, multiData);
61888             if (callback) callback(comboData);
61889         });
61890     }
61891
61892
61893     function setPlaceholder(d) {
61894         var ph;
61895         if (isMulti) {
61896             ph = field.placeholder() || t('inspector.add');
61897         } else {
61898             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
61899                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
61900             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
61901         }
61902
61903         container.selectAll('input')
61904             .attr('placeholder', ph + '…');
61905     }
61906
61907
61908     function change() {
61909         var val = tagValue(utilGetSetValue(input)),
61910             t$$1 = {};
61911
61912         if (isMulti) {
61913             if (!val) return;
61914             container.classed('active', false);
61915             utilGetSetValue(input, '');
61916             field.keys.push(field.key + val);
61917             t$$1[field.key + val] = 'yes';
61918             window.setTimeout(function() { input.node().focus(); }, 10);
61919
61920         } else {
61921             t$$1[field.key] = val;
61922         }
61923
61924         dispatch$$1.call('change', this, t$$1);
61925     }
61926
61927
61928     function removeMultikey(d) {
61929         event.stopPropagation();
61930         var t$$1 = {};
61931         t$$1[d.key] = undefined;
61932         dispatch$$1.call('change', this, t$$1);
61933     }
61934
61935
61936     function combo(selection$$1) {
61937         if (isMulti) {
61938             container = selection$$1.selectAll('ul').data([0]);
61939
61940             container = container.enter()
61941                 .append('ul')
61942                 .attr('class', 'form-field-multicombo')
61943                 .on('click', function() {
61944                     window.setTimeout(function() { input.node().focus(); }, 10);
61945                 })
61946                 .merge(container);
61947
61948         } else {
61949             container = selection$$1;
61950         }
61951
61952         input = container.selectAll('input')
61953             .data([0]);
61954
61955         input = input.enter()
61956             .append('input')
61957             .attr('type', 'text')
61958             .attr('id', 'preset-input-' + field.id)
61959             .call(utilNoAuto)
61960             .call(initCombo, selection$$1)
61961             .merge(input);
61962
61963         if (isNetwork && nominatim && entity) {
61964             var center = entity.extent(context.graph()).center();
61965             nominatim.countryCode(center, function (err, code) {
61966                 country = code;
61967             });
61968         }
61969
61970         input
61971             .on('change', change)
61972             .on('blur', change);
61973
61974         if (isMulti) {
61975             combobox
61976                 .on('accept', function() {
61977                     input.node().blur();
61978                     input.node().focus();
61979                 });
61980
61981             input
61982                 .on('focus', function() { container.classed('active', true); });
61983         }
61984     }
61985
61986
61987     combo.tags = function(tags) {
61988         if (isMulti) {
61989             multiData = [];
61990
61991             // Build multiData array containing keys already set..
61992             Object.keys(tags).forEach(function(key) {
61993                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
61994
61995                 var suffix = key.substring(field.key.length);
61996                 multiData.push({
61997                     key: key,
61998                     value: displayValue(suffix)
61999                 });
62000             });
62001
62002             // Set keys for form-field modified (needed for undo and reset buttons)..
62003             field.keys = lodash.map(multiData, 'key');
62004
62005             // Exclude existing multikeys from combo options..
62006             var available = objectDifference(comboData, multiData);
62007             combobox.data(available);
62008
62009             // Hide 'Add' button if this field uses fixed set of
62010             // translateable optstrings and they're all currently used..
62011             container.selectAll('.combobox-input, .combobox-caret')
62012                 .classed('hide', optstrings && !available.length);
62013
62014
62015             // Render chips
62016             var chips = container.selectAll('.chips')
62017                 .data(multiData);
62018
62019             chips.exit()
62020                 .remove();
62021
62022             var enter = chips.enter()
62023                 .insert('li', 'input')
62024                 .attr('class', 'chips');
62025
62026             enter.append('span');
62027             enter.append('a');
62028
62029             chips = chips.merge(enter);
62030
62031             chips.select('span')
62032                 .text(function(d) { return d.value; });
62033
62034             chips.select('a')
62035                 .on('click', removeMultikey)
62036                 .attr('class', 'remove')
62037                 .text('×');
62038
62039         } else {
62040             utilGetSetValue(input, displayValue(tags[field.key]));
62041         }
62042     };
62043
62044
62045     combo.focus = function() {
62046         input.node().focus();
62047     };
62048
62049
62050     combo.entity = function(_) {
62051         if (!arguments.length) return entity;
62052         entity = _;
62053         return combo;
62054     };
62055
62056
62057     return utilRebind(combo, dispatch$$1, 'on');
62058 }
62059
62060 function uiFieldText(field, context) {
62061     var dispatch$$1 = dispatch('change'),
62062         nominatim = services.geocoder,
62063         input,
62064         entity;
62065
62066
62067     function i(selection$$1) {
62068         var fieldId = 'preset-input-' + field.id;
62069
62070         input = selection$$1.selectAll('input')
62071             .data([0]);
62072
62073         input = input.enter()
62074             .append('input')
62075             .attr('type', field.type)
62076             .attr('id', fieldId)
62077             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62078             .call(utilNoAuto)
62079             .merge(input);
62080
62081         input
62082             .on('input', change(true))
62083             .on('blur', change())
62084             .on('change', change());
62085
62086         if (field.type === 'tel' && nominatim && entity) {
62087             var center = entity.extent(context.graph()).center();
62088             nominatim.countryCode(center, function (err, countryCode) {
62089                 if (err || !dataPhoneFormats[countryCode]) return;
62090                 selection$$1.selectAll('#' + fieldId)
62091                     .attr('placeholder', dataPhoneFormats[countryCode]);
62092             });
62093
62094         } else if (field.type === 'number') {
62095             input.attr('type', 'text');
62096
62097             var spinControl = selection$$1.selectAll('.spin-control')
62098                 .data([0]);
62099
62100             var enter = spinControl.enter()
62101                 .append('div')
62102                 .attr('class', 'spin-control');
62103
62104             enter
62105                 .append('button')
62106                 .datum(1)
62107                 .attr('class', 'increment')
62108                 .attr('tabindex', -1);
62109
62110             enter
62111                 .append('button')
62112                 .datum(-1)
62113                 .attr('class', 'decrement')
62114                 .attr('tabindex', -1);
62115
62116             spinControl = spinControl
62117                 .merge(enter);
62118
62119             spinControl.selectAll('button')
62120                 .on('click', function(d) {
62121                     event.preventDefault();
62122                     var num = parseInt(input.node().value || 0, 10);
62123                     if (!isNaN(num)) input.node().value = num + d;
62124                     change()();
62125                 });
62126         }
62127     }
62128
62129
62130     function change(onInput) {
62131         return function() {
62132             var t$$1 = {};
62133             t$$1[field.key] = utilGetSetValue(input) || undefined;
62134             dispatch$$1.call('change', this, t$$1, onInput);
62135         };
62136     }
62137
62138
62139     i.entity = function(_) {
62140         if (!arguments.length) return entity;
62141         entity = _;
62142         return i;
62143     };
62144
62145
62146     i.tags = function(tags) {
62147         utilGetSetValue(input, tags[field.key] || '');
62148     };
62149
62150
62151     i.focus = function() {
62152         var node = input.node();
62153         if (node) node.focus();
62154     };
62155
62156     return utilRebind(i, dispatch$$1, 'on');
62157 }
62158
62159 function uiFieldAccess(field) {
62160     var dispatch$$1 = dispatch('change'),
62161         items;
62162
62163     function access(selection$$1) {
62164         var wrap = selection$$1.selectAll('.preset-input-wrap')
62165             .data([0]);
62166
62167         wrap = wrap.enter()
62168             .append('div')
62169             .attr('class', 'cf preset-input-wrap')
62170             .append('ul')
62171             .merge(wrap);
62172
62173         var list = wrap.selectAll('ul')
62174             .data([0]);
62175
62176         list = list.enter()
62177             .append('ul')
62178             .merge(list);
62179
62180
62181         items = list.selectAll('li')
62182             .data(field.keys);
62183
62184         // Enter
62185         var enter = items.enter()
62186             .append('li')
62187             .attr('class', function(d) { return 'cf preset-access-' + d; });
62188
62189         enter
62190             .append('span')
62191             .attr('class', 'col6 label preset-label-access')
62192             .attr('for', function(d) { return 'preset-input-access-' + d; })
62193             .text(function(d) { return field.t('types.' + d); });
62194
62195         enter
62196             .append('div')
62197             .attr('class', 'col6 preset-input-access-wrap')
62198             .append('input')
62199             .attr('type', 'text')
62200             .attr('class', 'preset-input-access')
62201             .attr('id', function(d) { return 'preset-input-access-' + d; })
62202             .call(utilNoAuto)
62203             .each(function(d) {
62204                 select(this)
62205                     .call(d3combobox()
62206                         .data(access.options(d)));
62207             });
62208
62209
62210         // Update
62211         items = items.merge(enter);
62212
62213         wrap.selectAll('.preset-input-access')
62214             .on('change', change)
62215             .on('blur', change);
62216     }
62217
62218
62219     function change(d) {
62220         var tag = {};
62221         tag[d] = utilGetSetValue(select(this)) || undefined;
62222         dispatch$$1.call('change', this, tag);
62223     }
62224
62225
62226     access.options = function(type) {
62227         var options = ['no', 'permissive', 'private', 'destination'];
62228
62229         if (type !== 'access') {
62230             options.unshift('yes');
62231             options.push('designated');
62232
62233             if (type === 'bicycle') {
62234                 options.push('dismount');
62235             }
62236         }
62237
62238         return options.map(function(option) {
62239             return {
62240                 title: field.t('options.' + option + '.description'),
62241                 value: option
62242             };
62243         });
62244     };
62245
62246
62247     var placeholders = {
62248         footway: {
62249             foot: 'designated',
62250             motor_vehicle: 'no'
62251         },
62252         steps: {
62253             foot: 'yes',
62254             motor_vehicle: 'no',
62255             bicycle: 'no',
62256             horse: 'no'
62257         },
62258         pedestrian: {
62259             foot: 'yes',
62260             motor_vehicle: 'no'
62261         },
62262         cycleway: {
62263             motor_vehicle: 'no',
62264             bicycle: 'designated'
62265         },
62266         bridleway: {
62267             motor_vehicle: 'no',
62268             horse: 'designated'
62269         },
62270         path: {
62271             foot: 'yes',
62272             motor_vehicle: 'no',
62273             bicycle: 'yes',
62274             horse: 'yes'
62275         },
62276         motorway: {
62277             foot: 'no',
62278             motor_vehicle: 'yes',
62279             bicycle: 'no',
62280             horse: 'no'
62281         },
62282         trunk: {
62283             motor_vehicle: 'yes'
62284         },
62285         primary: {
62286             foot: 'yes',
62287             motor_vehicle: 'yes',
62288             bicycle: 'yes',
62289             horse: 'yes'
62290         },
62291         secondary: {
62292             foot: 'yes',
62293             motor_vehicle: 'yes',
62294             bicycle: 'yes',
62295             horse: 'yes'
62296         },
62297         tertiary: {
62298             foot: 'yes',
62299             motor_vehicle: 'yes',
62300             bicycle: 'yes',
62301             horse: 'yes'
62302         },
62303         residential: {
62304             foot: 'yes',
62305             motor_vehicle: 'yes',
62306             bicycle: 'yes',
62307             horse: 'yes'
62308         },
62309         unclassified: {
62310             foot: 'yes',
62311             motor_vehicle: 'yes',
62312             bicycle: 'yes',
62313             horse: 'yes'
62314         },
62315         service: {
62316             foot: 'yes',
62317             motor_vehicle: 'yes',
62318             bicycle: 'yes',
62319             horse: 'yes'
62320         },
62321         motorway_link: {
62322             foot: 'no',
62323             motor_vehicle: 'yes',
62324             bicycle: 'no',
62325             horse: 'no'
62326         },
62327         trunk_link: {
62328             motor_vehicle: 'yes'
62329         },
62330         primary_link: {
62331             foot: 'yes',
62332             motor_vehicle: 'yes',
62333             bicycle: 'yes',
62334             horse: 'yes'
62335         },
62336         secondary_link: {
62337             foot: 'yes',
62338             motor_vehicle: 'yes',
62339             bicycle: 'yes',
62340             horse: 'yes'
62341         },
62342         tertiary_link: {
62343             foot: 'yes',
62344             motor_vehicle: 'yes',
62345             bicycle: 'yes',
62346             horse: 'yes'
62347         }
62348     };
62349
62350
62351     access.tags = function(tags) {
62352         utilGetSetValue(items.selectAll('.preset-input-access'),
62353             function(d) { return tags[d] || ''; })
62354             .attr('placeholder', function() {
62355                 return tags.access ? tags.access : field.placeholder();
62356             });
62357
62358         items.selectAll('#preset-input-access-access')
62359             .attr('placeholder', 'yes');
62360
62361         lodash.forEach(placeholders[tags.highway], function(v, k) {
62362             items.selectAll('#preset-input-access-' + k)
62363                 .attr('placeholder', function() { return (tags.access || v); });
62364         });
62365     };
62366
62367
62368     access.focus = function() {
62369         items.selectAll('.preset-input-access')
62370             .node().focus();
62371     };
62372
62373
62374     return utilRebind(access, dispatch$$1, 'on');
62375 }
62376
62377 function uiFieldAddress(field, context) {
62378     var dispatch$$1 = dispatch('init', 'change'),
62379         nominatim = services.geocoder,
62380         wrap = select(null),
62381         isInitialized = false,
62382         entity;
62383
62384     function getNearStreets() {
62385         var extent$$1 = entity.extent(context.graph()),
62386             l = extent$$1.center(),
62387             box = geoExtent$$1(l).padByMeters(200);
62388
62389         var streets = context.intersects(box)
62390             .filter(isAddressable)
62391             .map(function(d) {
62392                 var loc = context.projection([
62393                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
62394                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
62395                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
62396                 return {
62397                     title: d.tags.name,
62398                     value: d.tags.name,
62399                     dist: choice.distance
62400                 };
62401             })
62402             .sort(function(a, b) {
62403                 return a.dist - b.dist;
62404             });
62405
62406         return lodash.uniqBy(streets, 'value');
62407
62408         function isAddressable(d) {
62409             return d.tags.highway && d.tags.name && d.type === 'way';
62410         }
62411     }
62412
62413
62414     function getNearCities() {
62415         var extent$$1 = entity.extent(context.graph()),
62416             l = extent$$1.center(),
62417             box = geoExtent$$1(l).padByMeters(200);
62418
62419         var cities = context.intersects(box)
62420             .filter(isAddressable)
62421             .map(function(d) {
62422                 return {
62423                     title: d.tags['addr:city'] || d.tags.name,
62424                     value: d.tags['addr:city'] || d.tags.name,
62425                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62426                 };
62427             })
62428             .sort(function(a, b) {
62429                 return a.dist - b.dist;
62430             });
62431
62432         return lodash.uniqBy(cities, 'value');
62433
62434
62435         function isAddressable(d) {
62436             if (d.tags.name &&
62437                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
62438                 return true;
62439
62440             if (d.tags.place && d.tags.name && (
62441                     d.tags.place === 'city' ||
62442                     d.tags.place === 'town' ||
62443                     d.tags.place === 'village'))
62444                 return true;
62445
62446             if (d.tags['addr:city']) return true;
62447
62448             return false;
62449         }
62450     }
62451
62452     function getNearValues(key) {
62453         var extent$$1 = entity.extent(context.graph()),
62454             l = extent$$1.center(),
62455             box = geoExtent$$1(l).padByMeters(200);
62456
62457         var results = context.intersects(box)
62458             .filter(function hasTag(d) {
62459                 return d.tags[key];
62460             })
62461             .map(function(d) {
62462                 return {
62463                     title: d.tags[key],
62464                     value: d.tags[key],
62465                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62466                 };
62467             })
62468             .sort(function(a, b) {
62469                 return a.dist - b.dist;
62470             });
62471
62472         return lodash.uniqBy(results, 'value');
62473     }
62474
62475
62476     function initCallback(err, countryCode) {
62477         if (err) return;
62478
62479         var addressFormat = lodash.find(dataAddressFormats, function (a) {
62480             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
62481         }) || lodash.first(dataAddressFormats);
62482
62483         var widths = addressFormat.widths || {
62484             housenumber: 1/3, street: 2/3,
62485             city: 2/3, state: 1/4, postcode: 1/3
62486         };
62487
62488         function row(r) {
62489             // Normalize widths.
62490             var total = lodash.reduce(r, function(sum$$1, field) {
62491                 return sum$$1 + (widths[field] || 0.5);
62492             }, 0);
62493
62494             return r.map(function (field) {
62495                 return {
62496                     id: field,
62497                     width: (widths[field] || 0.5) / total
62498                 };
62499             });
62500         }
62501
62502         wrap.selectAll('div.addr-row')
62503             .data(addressFormat.format)
62504             .enter()
62505             .append('div')
62506             .attr('class', 'addr-row')
62507             .selectAll('input')
62508             .data(row)
62509             .enter()
62510             .append('input')
62511             .property('type', 'text')
62512             .attr('placeholder', function (d) {
62513                 var localkey = d.id + '!' + countryCode,
62514                     tkey = field.strings.placeholders[localkey] ? localkey : d.id;
62515                 return field.t('placeholders.' + tkey);
62516             })
62517             .attr('class', function (d) { return 'addr-' + d.id; })
62518             .call(utilNoAuto)
62519             .style('width', function (d) { return d.width * 100 + '%'; });
62520
62521         // Update
62522
62523         // setup dropdowns for common address tags
62524         var dropdowns = addressFormat.dropdowns || [
62525             'city', 'county', 'country', 'district', 'hamlet',
62526             'neighbourhood', 'place', 'postcode', 'province',
62527             'quarter', 'state', 'street', 'subdistrict', 'suburb'
62528         ];
62529
62530         // If fields exist for any of these tags, create dropdowns to pick nearby values..
62531         dropdowns.forEach(function(tag) {
62532             var nearValues = (tag === 'street') ? getNearStreets
62533                     : (tag === 'city') ? getNearCities
62534                     : getNearValues;
62535
62536             wrap.selectAll('input.addr-' + tag)
62537                 .call(d3combobox()
62538                     .minItems(1)
62539                     .fetcher(function(value, callback) {
62540                         callback(nearValues('addr:' + tag));
62541                     }));
62542         });
62543
62544         wrap.selectAll('input')
62545             .on('blur', change())
62546             .on('change', change());
62547
62548         wrap.selectAll('input:not(.combobox-input)')
62549             .on('input', change(true));
62550
62551         dispatch$$1.call('init');
62552         isInitialized = true;
62553     }
62554
62555
62556     function address(selection$$1) {
62557         isInitialized = false;
62558
62559         wrap = selection$$1.selectAll('.preset-input-wrap')
62560             .data([0]);
62561
62562         wrap = wrap.enter()
62563             .append('div')
62564             .attr('class', 'preset-input-wrap')
62565             .merge(wrap);
62566
62567         if (nominatim && entity) {
62568             var center = entity.extent(context.graph()).center();
62569             nominatim.countryCode(center, initCallback);
62570         }
62571     }
62572
62573
62574     function change(onInput) {
62575         return function() {
62576             var tags = {};
62577
62578             wrap.selectAll('input')
62579                 .each(function (field) {
62580                     tags['addr:' + field.id] = this.value || undefined;
62581                 });
62582
62583             dispatch$$1.call('change', this, tags, onInput);
62584         };
62585     }
62586
62587
62588     function updateTags(tags) {
62589         utilGetSetValue(wrap.selectAll('input'), function (field) {
62590             return tags['addr:' + field.id] || '';
62591         });
62592     }
62593
62594
62595     address.entity = function(_) {
62596         if (!arguments.length) return entity;
62597         entity = _;
62598         return address;
62599     };
62600
62601
62602     address.tags = function(tags) {
62603         if (isInitialized) {
62604             updateTags(tags);
62605         } else {
62606             dispatch$$1.on('init', function () {
62607                 dispatch$$1.on('init', null);
62608                 updateTags(tags);
62609             });
62610         }
62611     };
62612
62613
62614     address.focus = function() {
62615         var node = wrap.selectAll('input').node();
62616         if (node) node.focus();
62617     };
62618
62619
62620     return utilRebind(address, dispatch$$1, 'on');
62621 }
62622
62623 function uiFieldCycleway(field) {
62624     var dispatch$$1 = dispatch('change'),
62625         items = select(null);
62626
62627
62628     function cycleway(selection$$1) {
62629
62630         function stripcolon(s) {
62631             return s.replace(':', '');
62632         }
62633
62634
62635         var wrap = selection$$1.selectAll('.preset-input-wrap')
62636             .data([0]);
62637
62638         wrap = wrap.enter()
62639             .append('div')
62640             .attr('class', 'cf preset-input-wrap')
62641             .merge(wrap);
62642
62643
62644         var div = wrap.selectAll('ul')
62645             .data([0]);
62646
62647         div = div.enter()
62648             .append('ul')
62649             .merge(div);
62650
62651
62652         items = div.selectAll('li')
62653             .data(field.keys);
62654
62655         var enter = items.enter()
62656             .append('li')
62657             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
62658
62659         enter
62660             .append('span')
62661             .attr('class', 'col6 label preset-label-cycleway')
62662             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
62663             .text(function(d) { return field.t('types.' + d); });
62664
62665         enter
62666             .append('div')
62667             .attr('class', 'col6 preset-input-cycleway-wrap')
62668             .append('input')
62669             .attr('type', 'text')
62670             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
62671             .call(utilNoAuto)
62672             .each(function(d) {
62673                 select(this).call(d3combobox().data(cycleway.options(d)));
62674             });
62675
62676
62677         // Update
62678         wrap.selectAll('.preset-input-cycleway')
62679             .on('change', change)
62680             .on('blur', change);
62681     }
62682
62683
62684     function change() {
62685         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
62686             right = utilGetSetValue(select('.preset-input-cyclewayright')),
62687             tag = {};
62688
62689         if (left === 'none' || left === '') { left = undefined; }
62690         if (right === 'none' || right === '') { right = undefined; }
62691
62692         // Always set both left and right as changing one can affect the other
62693         tag = {
62694             cycleway: undefined,
62695             'cycleway:left': left,
62696             'cycleway:right': right
62697         };
62698
62699         // If the left and right tags match, use the cycleway tag to tag both
62700         // sides the same way
62701         if (left === right) {
62702             tag = {
62703                 cycleway: left,
62704                 'cycleway:left': undefined,
62705                 'cycleway:right': undefined
62706             };
62707         }
62708
62709         dispatch$$1.call('change', this, tag);
62710     }
62711
62712
62713     cycleway.options = function() {
62714         return keys(field.strings.options).map(function(option) {
62715             return {
62716                 title: field.t('options.' + option + '.description'),
62717                 value: option
62718             };
62719         });
62720     };
62721
62722
62723     cycleway.tags = function(tags) {
62724         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
62725                 // If cycleway is set, always return that
62726                 if (tags.cycleway) {
62727                     return tags.cycleway;
62728                 }
62729                 return tags[d] || '';
62730             })
62731             .attr('placeholder', field.placeholder());
62732     };
62733
62734
62735     cycleway.focus = function() {
62736         items.selectAll('.preset-input-cycleway')
62737             .node().focus();
62738     };
62739
62740
62741     return utilRebind(cycleway, dispatch$$1, 'on');
62742 }
62743
62744 function uiFieldLanes(field, context) {
62745     var dispatch$$1 = dispatch('change'),
62746         LANE_WIDTH = 40,
62747         LANE_HEIGHT = 200,
62748         wayID,
62749         lanesData;
62750
62751     function lanes(selection$$1) {
62752         lanesData = context.entity(wayID).lanes();
62753
62754         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62755             selection$$1.call(lanes.off);
62756             return;
62757         }
62758
62759         var wrap = selection$$1.selectAll('.preset-input-wrap')
62760             .data([0]);
62761
62762         wrap = wrap.enter()
62763             .append('div')
62764             .attr('class', 'preset-input-wrap')
62765             .merge(wrap);
62766
62767         var surface =  wrap.selectAll('.surface')
62768             .data([0]);
62769
62770         var d = utilGetDimensions(wrap);
62771         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
62772
62773         surface = surface.enter()
62774             .append('svg')
62775             .attr('width', d[0])
62776             .attr('height', 300)
62777             .attr('class', 'surface')
62778             .merge(surface);
62779
62780
62781         var lanesSelection = surface.selectAll('.lanes')
62782             .data([0]);
62783
62784         lanesSelection = lanesSelection.enter()
62785             .append('g')
62786             .attr('class', 'lanes')
62787             .merge(lanesSelection);
62788
62789         lanesSelection
62790             .attr('transform', function () {
62791                 return 'translate(' + (freeSpace / 2) + ', 0)';
62792             });
62793
62794
62795         var lane = lanesSelection.selectAll('.lane')
62796            .data(lanesData.lanes);
62797
62798         lane.exit()
62799             .remove();
62800
62801         var enter = lane.enter()
62802             .append('g')
62803             .attr('class', 'lane');
62804
62805         enter
62806             .append('g')
62807             .append('rect')
62808             .attr('y', 50)
62809             .attr('width', LANE_WIDTH)
62810             .attr('height', LANE_HEIGHT);
62811
62812         enter
62813             .append('g')
62814             .attr('class', 'forward')
62815             .append('text')
62816             .attr('y', 40)
62817             .attr('x', 14)
62818             .text('▲');
62819
62820         enter
62821             .append('g')
62822             .attr('class', 'bothways')
62823             .append('text')
62824             .attr('y', 40)
62825             .attr('x', 14)
62826             .text('▲▼');
62827
62828         enter
62829             .append('g')
62830             .attr('class', 'backward')
62831             .append('text')
62832             .attr('y', 40)
62833             .attr('x', 14)
62834             .text('▼');
62835
62836
62837         lane = lane
62838             .merge(enter);
62839
62840         lane
62841             .attr('transform', function(d) {
62842                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
62843             });
62844
62845         lane.select('.forward')
62846             .style('visibility', function(d) {
62847                 return d.direction === 'forward' ? 'visible' : 'hidden';
62848             });
62849
62850         lane.select('.bothways')
62851             .style('visibility', function(d) {
62852                 return d.direction === 'bothways' ? 'visible' : 'hidden';
62853             });
62854
62855         lane.select('.backward')
62856             .style('visibility', function(d) {
62857                 return d.direction === 'backward' ? 'visible' : 'hidden';
62858             });
62859     }
62860
62861
62862     lanes.entity = function(_) {
62863         if (!wayID || wayID !== _.id) {
62864             wayID = _.id;
62865         }
62866     };
62867
62868     lanes.tags = function() {};
62869     lanes.focus = function() {};
62870     lanes.off = function() {};
62871
62872     return utilRebind(lanes, dispatch$$1, 'on');
62873 }
62874
62875 function uiFieldLocalized(field, context) {
62876     var dispatch$$1 = dispatch('change', 'input'),
62877         wikipedia = services.wikipedia,
62878         input = select(null),
62879         localizedInputs = select(null),
62880         wikiTitles,
62881         entity;
62882
62883
62884     function localized(selection$$1) {
62885         input = selection$$1.selectAll('.localized-main')
62886             .data([0]);
62887
62888         input = input.enter()
62889             .append('input')
62890             .attr('type', 'text')
62891             .attr('id', 'preset-input-' + field.id)
62892             .attr('class', 'localized-main')
62893             .attr('placeholder', field.placeholder())
62894             .call(utilNoAuto)
62895             .merge(input);
62896
62897         if (field.id === 'name') {
62898             var preset = context.presets().match(entity, context.graph());
62899             input.call(d3combobox().fetcher(
62900                 utilSuggestNames(preset, dataSuggestions)
62901             ));
62902         }
62903
62904         input
62905             .on('input', change(true))
62906             .on('blur', change())
62907             .on('change', change());
62908
62909
62910         var translateButton = selection$$1.selectAll('.localized-add')
62911             .data([0]);
62912
62913         translateButton = translateButton.enter()
62914             .append('button')
62915             .attr('class', 'button-input-action localized-add minor')
62916             .attr('tabindex', -1)
62917             .call(svgIcon('#icon-plus'))
62918             .call(tooltip()
62919                 .title(t('translate.translate'))
62920                 .placement('left'))
62921             .merge(translateButton);
62922
62923         translateButton
62924             .on('click', addNew);
62925
62926
62927         localizedInputs = selection$$1.selectAll('.localized-wrap')
62928             .data([0]);
62929
62930         localizedInputs = localizedInputs.enter().append('div')
62931             .attr('class', 'localized-wrap')
62932             .merge(localizedInputs);
62933     }
62934
62935
62936     function addNew() {
62937         event.preventDefault();
62938         var data$$1 = localizedInputs.selectAll('div.entry').data();
62939         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
62940         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
62941         var isLangEn = defaultLang.indexOf('en') > -1;
62942         if (isLangEn || langExists) {
62943             defaultLang = '';
62944         }
62945         data$$1.push({ lang: defaultLang, value: '' });
62946         localizedInputs.call(render, data$$1);
62947     }
62948
62949
62950     function change(onInput) {
62951         return function() {
62952             var t$$1 = {};
62953             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
62954             dispatch$$1.call('change', this, t$$1, onInput);
62955         };
62956     }
62957
62958
62959     function key(lang) {
62960         return field.key + ':' + lang;
62961     }
62962
62963
62964     function changeLang(d) {
62965         var lang = utilGetSetValue(select(this)),
62966             t$$1 = {},
62967             language = lodash.find(dataWikipedia, function(d) {
62968                 return d[0].toLowerCase() === lang.toLowerCase() ||
62969                     d[1].toLowerCase() === lang.toLowerCase();
62970             });
62971
62972         if (language) lang = language[2];
62973
62974         if (d.lang && d.lang !== lang) {
62975             t$$1[key(d.lang)] = undefined;
62976         }
62977
62978         var value = utilGetSetValue(select(this.parentNode)
62979             .selectAll('.localized-value'));
62980
62981         if (lang && value) {
62982             t$$1[key(lang)] = value;
62983         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
62984             t$$1[key(lang)] = wikiTitles[d.lang];
62985         }
62986
62987         d.lang = lang;
62988         dispatch$$1.call('change', this, t$$1);
62989     }
62990
62991
62992     function changeValue(d) {
62993         if (!d.lang) return;
62994         var t$$1 = {};
62995         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
62996         dispatch$$1.call('change', this, t$$1);
62997     }
62998
62999
63000     function fetcher(value, cb) {
63001         var v = value.toLowerCase();
63002
63003         cb(dataWikipedia.filter(function(d) {
63004             return d[0].toLowerCase().indexOf(v) >= 0 ||
63005             d[1].toLowerCase().indexOf(v) >= 0 ||
63006             d[2].toLowerCase().indexOf(v) >= 0;
63007         }).map(function(d) {
63008             return { value: d[1] };
63009         }));
63010     }
63011
63012
63013     function render(selection$$1, data$$1) {
63014         var wraps = selection$$1.selectAll('div.entry').
63015             data(data$$1, function(d) { return d.lang; });
63016
63017         wraps.exit()
63018             .transition()
63019             .duration(200)
63020             .style('max-height','0px')
63021             .style('opacity', '0')
63022             .style('top','-10px')
63023             .remove();
63024
63025         var innerWrap = wraps.enter()
63026             .insert('div', ':first-child');
63027
63028         innerWrap.attr('class', 'entry')
63029             .each(function() {
63030                 var wrap = select(this);
63031                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
63032
63033                 var label = wrap
63034                     .append('label')
63035                     .attr('class','form-label')
63036                     .text(t('translate.localized_translation_label'))
63037                     .attr('for','localized-lang');
63038
63039                 label
63040                     .append('button')
63041                     .attr('class', 'minor remove')
63042                     .on('click', function(d){
63043                         event.preventDefault();
63044                         var t$$1 = {};
63045                         t$$1[key(d.lang)] = undefined;
63046                         dispatch$$1.call('change', this, t$$1);
63047                         select(this.parentNode.parentNode)
63048                             .style('top','0')
63049                             .style('max-height','240px')
63050                             .transition()
63051                             .style('opacity', '0')
63052                             .style('max-height','0px')
63053                             .remove();
63054                     })
63055                     .call(svgIcon('#operation-delete'));
63056
63057                 wrap
63058                     .append('input')
63059                     .attr('class', 'localized-lang')
63060                     .attr('type', 'text')
63061                     .attr('placeholder',t('translate.localized_translation_language'))
63062                     .on('blur', changeLang)
63063                     .on('change', changeLang)
63064                     .call(langcombo);
63065
63066                 wrap
63067                     .append('input')
63068                     .on('blur', changeValue)
63069                     .on('change', changeValue)
63070                     .attr('type', 'text')
63071                     .attr('placeholder', t('translate.localized_translation_name'))
63072                     .attr('class', 'localized-value');
63073             });
63074
63075         innerWrap
63076             .style('margin-top', '0px')
63077             .style('max-height', '0px')
63078             .style('opacity', '0')
63079             .transition()
63080             .duration(200)
63081             .style('margin-top', '10px')
63082             .style('max-height', '240px')
63083             .style('opacity', '1')
63084             .on('end', function() {
63085                 select(this)
63086                     .style('max-height', '')
63087                     .style('overflow', 'visible');
63088             });
63089
63090
63091         var entry = selection$$1.selectAll('.entry');
63092
63093         utilGetSetValue(entry.select('.localized-lang'), function(d) {
63094                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
63095                 return lang ? lang[1] : d.lang;
63096             });
63097
63098         utilGetSetValue(entry.select('.localized-value'),
63099             function(d) { return d.value; });
63100     }
63101
63102
63103     localized.tags = function(tags) {
63104         // Fetch translations from wikipedia
63105         if (tags.wikipedia && !wikiTitles) {
63106             wikiTitles = {};
63107             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
63108             if (wm && wm[0] && wm[1]) {
63109                 wikipedia.translations(wm[1], wm[2], function(d) {
63110                     wikiTitles = d;
63111                 });
63112             }
63113         }
63114
63115         utilGetSetValue(input, tags[field.key] || '');
63116
63117         var postfixed = [], k, m;
63118         for (k in tags) {
63119             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
63120             if (m && m[1] === field.key && m[2]) {
63121                 postfixed.push({ lang: m[2], value: tags[k] });
63122             }
63123         }
63124
63125         localizedInputs.call(render, postfixed.reverse());
63126     };
63127
63128
63129     localized.focus = function() {
63130         input.node().focus();
63131     };
63132
63133
63134     localized.entity = function(_) {
63135         if (!arguments.length) return entity;
63136         entity = _;
63137         return localized;
63138     };
63139
63140     return utilRebind(localized, dispatch$$1, 'on');
63141 }
63142
63143 function uiFieldMaxspeed(field, context) {
63144     var dispatch$$1 = dispatch('change'),
63145         entity,
63146         isImperial,
63147         unitInput = select(null),
63148         input = select(null),
63149         combobox;
63150
63151     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
63152         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
63153
63154
63155     function maxspeed(selection$$1) {
63156         combobox = d3combobox();
63157         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
63158
63159         input = selection$$1.selectAll('#preset-input-' + field.id)
63160             .data([0]);
63161
63162         input = input.enter()
63163             .append('input')
63164             .attr('type', 'text')
63165             .attr('id', 'preset-input-' + field.id)
63166             .attr('placeholder', field.placeholder())
63167             .call(utilNoAuto)
63168             .call(combobox)
63169             .merge(input);
63170
63171         input
63172             .on('change', change)
63173             .on('blur', change);
63174
63175         var childNodes = context.graph().childNodes(context.entity(entity.id)),
63176             loc = childNodes[~~(childNodes.length/2)].loc;
63177
63178         isImperial = lodash.some(dataImperial.features, function(f) {
63179             return lodash.some(f.geometry.coordinates, function(d) {
63180                 return geoPointInPolygon(loc, d);
63181             });
63182         });
63183
63184         unitInput = selection$$1.selectAll('input.maxspeed-unit')
63185             .data([0]);
63186
63187         unitInput = unitInput.enter()
63188             .append('input')
63189             .attr('type', 'text')
63190             .attr('class', 'maxspeed-unit')
63191             .call(unitCombobox)
63192             .merge(unitInput);
63193
63194         unitInput
63195             .on('blur', changeUnits)
63196             .on('change', changeUnits);
63197
63198
63199         function changeUnits() {
63200             isImperial = utilGetSetValue(unitInput) === 'mph';
63201             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63202             setSuggestions();
63203             change();
63204         }
63205     }
63206
63207
63208     function setSuggestions() {
63209         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
63210         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63211     }
63212
63213
63214     function comboValues(d) {
63215         return {
63216             value: d.toString(),
63217             title: d.toString()
63218         };
63219     }
63220
63221
63222     function change() {
63223         var tag = {},
63224             value = utilGetSetValue(input);
63225
63226         if (!value) {
63227             tag[field.key] = undefined;
63228         } else if (isNaN(value) || !isImperial) {
63229             tag[field.key] = value;
63230         } else {
63231             tag[field.key] = value + ' mph';
63232         }
63233
63234         dispatch$$1.call('change', this, tag);
63235     }
63236
63237
63238     maxspeed.tags = function(tags) {
63239         var value = tags[field.key];
63240
63241         if (value && value.indexOf('mph') >= 0) {
63242             value = parseInt(value, 10);
63243             isImperial = true;
63244         } else if (value) {
63245             isImperial = false;
63246         }
63247
63248         setSuggestions();
63249         utilGetSetValue(input, value || '');
63250     };
63251
63252
63253     maxspeed.focus = function() {
63254         input.node().focus();
63255     };
63256
63257
63258     maxspeed.entity = function(_) {
63259         entity = _;
63260     };
63261
63262
63263     return utilRebind(maxspeed, dispatch$$1, 'on');
63264 }
63265
63266 function uiFieldRadio(field) {
63267     var dispatch$$1 = dispatch('change'),
63268         placeholder = select(null),
63269         labels = select(null),
63270         radios = select(null);
63271
63272
63273     function radio(selection$$1) {
63274         selection$$1.classed('preset-radio', true);
63275
63276         var wrap = selection$$1.selectAll('.preset-input-wrap')
63277             .data([0]);
63278
63279         var enter = wrap.enter()
63280             .append('div')
63281             .attr('class', 'preset-input-wrap toggle-list');
63282
63283         enter
63284             .append('span')
63285             .attr('class', 'placeholder');
63286
63287         wrap = wrap
63288             .merge(enter);
63289
63290
63291         placeholder = wrap.selectAll('.placeholder');
63292
63293         labels = wrap.selectAll('label')
63294             .data(field.options || field.keys);
63295
63296         enter = labels.enter()
63297             .append('label');
63298
63299         enter.append('input')
63300             .attr('type', 'radio')
63301             .attr('name', field.id)
63302             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
63303             .attr('checked', false);
63304
63305         enter.append('span')
63306             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
63307
63308         labels = labels
63309             .merge(enter);
63310
63311         radios = labels.selectAll('input')
63312             .on('change', change);
63313     }
63314
63315
63316     function change() {
63317         var t$$1 = {};
63318         if (field.key) t$$1[field.key] = undefined;
63319         radios.each(function(d) {
63320             var active$$1 = select(this).property('checked');
63321             if (field.key) {
63322                 if (active$$1) t$$1[field.key] = d;
63323             } else {
63324                 t$$1[d] = active$$1 ? 'yes' : undefined;
63325             }
63326         });
63327         dispatch$$1.call('change', this, t$$1);
63328     }
63329
63330
63331     radio.tags = function(tags) {
63332         function checked(d) {
63333             if (field.key) {
63334                 return tags[field.key] === d;
63335             } else {
63336                 return !!(tags[d] && tags[d] !== 'no');
63337             }
63338         }
63339
63340         labels.classed('active', checked);
63341         radios.property('checked', checked);
63342         var selection$$1 = radios.filter(function() { return this.checked; });
63343         if (selection$$1.empty()) {
63344             placeholder.text(t('inspector.none'));
63345         } else {
63346             placeholder.text(selection$$1.attr('value'));
63347         }
63348     };
63349
63350
63351     radio.focus = function() {
63352         radios.node().focus();
63353     };
63354
63355
63356     return utilRebind(radio, dispatch$$1, 'on');
63357 }
63358
63359 function uiFieldRestrictions(field, context) {
63360     var dispatch$$1 = dispatch('change'),
63361         breathe = behaviorBreathe(context),
63362         hover = behaviorHover(context),
63363         initialized = false,
63364         vertexID,
63365         fromNodeID;
63366
63367
63368     function restrictions(selection$$1) {
63369         // if form field is hidden or has detached from dom, clean up.
63370         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
63371             selection$$1.call(restrictions.off);
63372             return;
63373         }
63374
63375         var wrap = selection$$1.selectAll('.preset-input-wrap')
63376             .data([0]);
63377
63378         var enter = wrap.enter()
63379             .append('div')
63380             .attr('class', 'preset-input-wrap');
63381
63382         enter
63383             .append('div')
63384             .attr('class', 'restriction-help');
63385
63386
63387         var intersection = osmIntersection(context.graph(), vertexID),
63388             graph = intersection.graph,
63389             vertex = graph.entity(vertexID),
63390             filter = utilFunctor(true),
63391             extent$$1 = geoExtent$$1(),
63392             projection = geoRawMercator();
63393
63394         var d = utilGetDimensions(wrap.merge(enter)),
63395             c = [d[0] / 2, d[1] / 2],
63396             z = 24;
63397
63398         projection
63399             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
63400
63401         var s = projection(vertex.loc);
63402
63403         projection
63404             .translate([c[0] - s[0], c[1] - s[1]])
63405             .clipExtent([[0, 0], d]);
63406
63407         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
63408             drawVertices = svgVertices$$1(projection, context),
63409             drawLines = svgLines$$1(projection, context),
63410             drawTurns = svgTurns(projection, context);
63411
63412         enter
63413             .call(drawLayers);
63414
63415         wrap = wrap
63416             .merge(enter);
63417
63418         var surface = wrap.selectAll('.surface');
63419
63420         if (!enter.empty()) {
63421             initialized = true;
63422             surface
63423                 .call(breathe)
63424                 .call(hover);
63425         }
63426
63427         surface
63428             .call(utilSetDimensions, d)
63429             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
63430             .call(drawLines, graph, intersection.ways, filter)
63431             .call(drawTurns, graph, intersection.turns(fromNodeID));
63432
63433         surface
63434             .on('click.restrictions', click)
63435             .on('mouseover.restrictions', mouseover)
63436             .on('mouseout.restrictions', mouseout);
63437
63438         surface
63439             .selectAll('.selected')
63440             .classed('selected', false);
63441
63442         if (fromNodeID) {
63443             surface
63444                 .selectAll('.' + intersection.highways[fromNodeID].id)
63445                 .classed('selected', true);
63446         }
63447
63448         mouseout();
63449
63450         context.history()
63451             .on('change.restrictions', render);
63452
63453         select(window)
63454             .on('resize.restrictions', function() {
63455                 utilSetDimensions(wrap, null);
63456                 render();
63457             });
63458
63459
63460         function click() {
63461             surface
63462                 .call(breathe.off)
63463                 .call(breathe);
63464
63465             var datum = event.target.__data__;
63466             if (datum instanceof osmEntity$$1) {
63467                 fromNodeID = intersection.adjacentNodeId(datum.id);
63468                 render();
63469             } else if (datum instanceof osmTurn) {
63470                 if (datum.restriction) {
63471                     context.perform(
63472                         actionUnrestrictTurn(datum, projection),
63473                         t('operations.restriction.annotation.delete')
63474                     );
63475                 } else {
63476                     context.perform(
63477                         actionRestrictTurn(datum, projection),
63478                         t('operations.restriction.annotation.create')
63479                     );
63480                 }
63481             }
63482         }
63483
63484
63485         function mouseover() {
63486             var datum = event.target.__data__;
63487             if (datum instanceof osmTurn) {
63488                 var graph = context.graph(),
63489                     presets = context.presets(),
63490                     preset;
63491
63492                 if (datum.restriction) {
63493                     preset = presets.match(graph.entity(datum.restriction), graph);
63494                 } else {
63495                     preset = presets.item('type/restriction/' +
63496                         osmInferRestriction(
63497                             graph,
63498                             datum.from,
63499                             datum.via,
63500                             datum.to,
63501                             projection
63502                         )
63503                     );
63504                 }
63505
63506                 wrap.selectAll('.restriction-help')
63507                     .text(t('operations.restriction.help.' +
63508                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
63509                         { restriction: preset.name() })
63510                     );
63511             }
63512         }
63513
63514
63515         function mouseout() {
63516             wrap.selectAll('.restriction-help')
63517                 .text(t('operations.restriction.help.' +
63518                     (fromNodeID ? 'toggle' : 'select'))
63519                 );
63520         }
63521
63522
63523         function render() {
63524             if (context.hasEntity(vertexID)) {
63525                 restrictions(selection$$1);
63526             }
63527         }
63528     }
63529
63530
63531     restrictions.entity = function(_) {
63532         if (!vertexID || vertexID !== _.id) {
63533             fromNodeID = null;
63534             vertexID = _.id;
63535         }
63536     };
63537
63538
63539     restrictions.tags = function() {};
63540     restrictions.focus = function() {};
63541
63542
63543     restrictions.off = function(selection$$1) {
63544         if (!initialized) return;
63545
63546         selection$$1.selectAll('.surface')
63547             .call(hover.off)
63548             .call(breathe.off)
63549             .on('click.restrictions', null)
63550             .on('mouseover.restrictions', null)
63551             .on('mouseout.restrictions', null);
63552
63553         context.history()
63554             .on('change.restrictions', null);
63555
63556         select(window)
63557             .on('resize.restrictions', null);
63558     };
63559
63560
63561     return utilRebind(restrictions, dispatch$$1, 'on');
63562 }
63563
63564 function uiFieldTextarea(field) {
63565     var dispatch$$1 = dispatch('change'),
63566         input = select(null);
63567
63568
63569     function textarea(selection$$1) {
63570         input = selection$$1.selectAll('textarea')
63571             .data([0]);
63572
63573         input = input.enter()
63574             .append('textarea')
63575             .attr('id', 'preset-input-' + field.id)
63576             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
63577             .attr('maxlength', 255)
63578             .call(utilNoAuto)
63579             .on('input', change(true))
63580             .on('blur', change())
63581             .on('change', change())
63582             .merge(input);
63583     }
63584
63585
63586     function change(onInput) {
63587         return function() {
63588             var t$$1 = {};
63589             t$$1[field.key] = utilGetSetValue(input) || undefined;
63590             dispatch$$1.call('change', this, t$$1, onInput);
63591         };
63592     }
63593
63594
63595     textarea.tags = function(tags) {
63596         utilGetSetValue(input, tags[field.key] || '');
63597     };
63598
63599
63600     textarea.focus = function() {
63601         input.node().focus();
63602     };
63603
63604
63605     return utilRebind(textarea, dispatch$$1, 'on');
63606 }
63607
63608 function uiFieldWikipedia(field, context) {
63609     var dispatch$$1 = dispatch('change'),
63610         wikipedia = services.wikipedia,
63611         wikidata = services.wikidata,
63612         link = select(null),
63613         lang = select(null),
63614         title = select(null),
63615         entity;
63616
63617
63618     function wiki(selection$$1) {
63619         var langcombo = d3combobox()
63620             .fetcher(function(value, cb) {
63621                 var v = value.toLowerCase();
63622
63623                 cb(dataWikipedia.filter(function(d) {
63624                     return d[0].toLowerCase().indexOf(v) >= 0 ||
63625                         d[1].toLowerCase().indexOf(v) >= 0 ||
63626                         d[2].toLowerCase().indexOf(v) >= 0;
63627                 }).map(function(d) {
63628                     return { value: d[1] };
63629                 }));
63630             });
63631
63632         var titlecombo = d3combobox()
63633             .fetcher(function(value, cb) {
63634                 if (!value) {
63635                     value = context.entity(entity.id).tags.name || '';
63636                 }
63637
63638                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
63639                 searchfn(language()[2], value, function(query, data$$1) {
63640                     cb(data$$1.map(function(d) {
63641                         return { value: d };
63642                     }));
63643                 });
63644             });
63645
63646
63647         lang = selection$$1.selectAll('input.wiki-lang')
63648             .data([0]);
63649
63650         lang = lang.enter()
63651             .append('input')
63652             .attr('type', 'text')
63653             .attr('class', 'wiki-lang')
63654             .attr('placeholder', t('translate.localized_translation_language'))
63655             .call(utilNoAuto)
63656             .merge(lang);
63657
63658         utilGetSetValue(lang, language()[1]);
63659
63660         lang
63661             .call(langcombo)
63662             .on('blur', changeLang)
63663             .on('change', changeLang);
63664
63665
63666         title = selection$$1.selectAll('input.wiki-title')
63667             .data([0]);
63668
63669         title = title.enter()
63670             .append('input')
63671             .attr('type', 'text')
63672             .attr('class', 'wiki-title')
63673             .attr('id', 'preset-input-' + field.id)
63674             .call(utilNoAuto)
63675             .merge(title);
63676
63677         title
63678             .call(titlecombo)
63679             .on('blur', blur)
63680             .on('change', change);
63681
63682
63683         link = selection$$1.selectAll('a.wiki-link')
63684             .data([0]);
63685
63686         link = link.enter()
63687             .append('a')
63688             .attr('class', 'wiki-link button-input-action minor')
63689             .attr('tabindex', -1)
63690             .attr('target', '_blank')
63691             .call(svgIcon('#icon-out-link', 'inline'))
63692             .merge(link);
63693     }
63694
63695
63696     function language() {
63697         var value = utilGetSetValue(lang).toLowerCase();
63698         var locale = utilDetect().locale.toLowerCase();
63699         var localeLanguage;
63700         return lodash.find(dataWikipedia, function(d) {
63701             if (d[2] === locale) localeLanguage = d;
63702             return d[0].toLowerCase() === value ||
63703                 d[1].toLowerCase() === value ||
63704                 d[2] === value;
63705         }) || localeLanguage || ['English', 'English', 'en'];
63706     }
63707
63708
63709     function changeLang() {
63710         utilGetSetValue(lang, language()[1]);
63711         change(true);
63712     }
63713
63714
63715     function blur() {
63716         change(true);
63717     }
63718
63719
63720     function change(skipWikidata) {
63721         var value = utilGetSetValue(title),
63722             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
63723             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63724             anchor,
63725             syncTags = {};
63726
63727         if (l) {
63728             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
63729             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
63730             if (m[3]) {
63731                 try {
63732                     // Best-effort `anchordecode:` implementation
63733                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
63734                 } catch (e) {
63735                     anchor = decodeURIComponent(m[3]);
63736                 }
63737                 value += '#' + anchor.replace(/_/g, ' ');
63738             }
63739             value = value.slice(0, 1).toUpperCase() + value.slice(1);
63740             utilGetSetValue(lang, l[1]);
63741             utilGetSetValue(title, value);
63742         }
63743
63744         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
63745         if (!skipWikidata) {
63746             syncTags.wikidata = undefined;
63747         }
63748
63749         dispatch$$1.call('change', this, syncTags);
63750
63751
63752         if (skipWikidata || !value || !language()[2]) return;
63753
63754         // attempt asynchronous update of wikidata tag..
63755         var initEntityId = entity.id,
63756             initWikipedia = context.entity(initEntityId).tags.wikipedia;
63757
63758         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
63759             if (!data$$1 || !Object.keys(data$$1).length) return;
63760             var qids = Object.keys(data$$1);
63761
63762             // 1. most recent change was a tag change
63763             var annotation = t('operations.change_tags.annotation'),
63764                 currAnnotation = context.history().undoAnnotation();
63765             if (currAnnotation !== annotation) return;
63766
63767             // 2. same entity exists and still selected
63768             var selectedIds = context.selectedIDs(),
63769                 currEntityId = selectedIds.length > 0 && selectedIds[0];
63770             if (currEntityId !== initEntityId) return;
63771
63772             // 3. wikipedia value has not changed
63773             var currTags = lodash.clone(context.entity(currEntityId).tags);
63774             if (initWikipedia !== currTags.wikipedia) return;
63775
63776             // ok to coalesce the update of wikidata tag into the previous tag change
63777             currTags.wikidata = qids && lodash.find(qids, function(id) {
63778                 return id.match(/^Q\d+$/);
63779             });
63780
63781             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
63782             dispatch$$1.call('change', this, currTags);
63783         });
63784     }
63785
63786
63787     wiki.tags = function(tags) {
63788         var value = tags[field.key] || '',
63789             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
63790             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63791             anchor = m && m[3];
63792
63793         // value in correct format
63794         if (l) {
63795             utilGetSetValue(lang, l[1]);
63796             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
63797             if (anchor) {
63798                 try {
63799                     // Best-effort `anchorencode:` implementation
63800                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
63801                 } catch (e) {
63802                     anchor = anchor.replace(/ /g, '_');
63803                 }
63804             }
63805             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
63806                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
63807
63808         // unrecognized value format
63809         } else {
63810             utilGetSetValue(title, value);
63811             if (value && value !== '') {
63812                 utilGetSetValue(lang, '');
63813             }
63814             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
63815         }
63816     };
63817
63818
63819     wiki.entity = function(_) {
63820         if (!arguments.length) return entity;
63821         entity = _;
63822         return wiki;
63823     };
63824
63825
63826     wiki.focus = function() {
63827         title.node().focus();
63828     };
63829
63830
63831     return utilRebind(wiki, dispatch$$1, 'on');
63832 }
63833
63834 var uiFields = {
63835     access: uiFieldAccess,
63836     address: uiFieldAddress,
63837     check: uiFieldCheck,
63838     defaultcheck: uiFieldCheck,
63839     combo: uiFieldCombo,
63840     typeCombo: uiFieldCombo,
63841     multiCombo: uiFieldCombo,
63842     networkCombo: uiFieldCombo,
63843     cycleway: uiFieldCycleway,
63844     text: uiFieldText,
63845     url: uiFieldText,
63846     number: uiFieldText,
63847     email: uiFieldText,
63848     tel: uiFieldText,
63849     localized: uiFieldLocalized,
63850     lanes: uiFieldLanes,
63851     maxspeed: uiFieldMaxspeed,
63852     radio: uiFieldRadio,
63853     restrictions: uiFieldRestrictions,
63854     textarea: uiFieldTextarea,
63855     wikipedia: uiFieldWikipedia
63856 };
63857
63858 function uiPreset(context) {
63859     var dispatch$$1 = dispatch('change'),
63860         state,
63861         fieldsArr,
63862         preset,
63863         tags,
63864         id;
63865
63866
63867     // Field Constructor
63868     function UIField(field, entity, show) {
63869         field = lodash.clone(field);
63870
63871         field.input = uiFields[field.type](field, context)
63872             .on('change', function(t$$1, onInput) {
63873                 dispatch$$1.call('change', field, t$$1, onInput);
63874             });
63875
63876         if (field.input.entity) field.input.entity(entity);
63877
63878         field.keys = field.keys || [field.key];
63879
63880         field.show = show;
63881
63882         field.shown = function() {
63883             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
63884         };
63885
63886         field.modified = function() {
63887             var original = context.graph().base().entities[entity.id];
63888             return lodash.some(field.keys, function(key) {
63889                 return original ? tags[key] !== original.tags[key] : tags[key];
63890             });
63891         };
63892
63893         field.revert = function() {
63894             var original = context.graph().base().entities[entity.id],
63895                 t$$1 = {};
63896             field.keys.forEach(function(key) {
63897                 t$$1[key] = original ? original.tags[key] : undefined;
63898             });
63899             return t$$1;
63900         };
63901
63902         field.present = function() {
63903             return lodash.some(field.keys, function(key) {
63904                 return tags[key];
63905             });
63906         };
63907
63908         field.remove = function() {
63909             var t$$1 = {};
63910             field.keys.forEach(function(key) {
63911                 t$$1[key] = undefined;
63912             });
63913             return t$$1;
63914         };
63915
63916         return field;
63917     }
63918
63919
63920     function fieldKey(field) {
63921         return field.id;
63922     }
63923
63924
63925     function presets(selection$$1) {
63926         selection$$1.call(uiDisclosure()
63927             .title(t('inspector.all_fields'))
63928             .expanded(context.storage('preset_fields.expanded') !== 'false')
63929             .on('toggled', toggled)
63930             .content(content)
63931         );
63932
63933         function toggled(expanded) {
63934             context.storage('preset_fields.expanded', expanded);
63935         }
63936     }
63937
63938
63939     function content(selection$$1) {
63940         if (!fieldsArr) {
63941             var entity = context.entity(id),
63942                 geometry = context.geometry(id),
63943                 presets = context.presets();
63944
63945             fieldsArr = [];
63946
63947             if (presets.field('name')) {
63948                 fieldsArr.push(UIField(presets.field('name'), entity));
63949             }
63950
63951             preset.fields.forEach(function(field) {
63952                 if (field.matchGeometry(geometry)) {
63953                     fieldsArr.push(UIField(field, entity, true));
63954                 }
63955             });
63956
63957             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
63958                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
63959             }
63960
63961             presets.universal().forEach(function(field) {
63962                 if (preset.fields.indexOf(field) < 0) {
63963                     fieldsArr.push(UIField(field, entity));
63964                 }
63965             });
63966         }
63967
63968         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
63969             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
63970
63971
63972         var form = selection$$1.selectAll('.preset-form')
63973             .data([0]);
63974
63975         form = form.enter()
63976             .append('div')
63977             .attr('class', 'preset-form inspector-inner fillL3')
63978             .merge(form);
63979
63980
63981         var fields = form.selectAll('.form-field')
63982             .data(shown, fieldKey);
63983
63984         fields.exit()
63985             .remove();
63986
63987         // Enter
63988         var enter = fields.enter()
63989             .append('div')
63990             .attr('class', function(field) {
63991                 return 'form-field form-field-' + field.id;
63992             });
63993
63994         var label = enter
63995             .append('label')
63996             .attr('class', 'form-label')
63997             .attr('for', function(field) { return 'preset-input-' + field.id; })
63998             .text(function(field) { return field.label(); });
63999
64000         var wrap = label
64001             .append('div')
64002             .attr('class', 'form-label-button-wrap');
64003
64004         wrap.append('button')
64005             .attr('class', 'remove-icon')
64006             .attr('tabindex', -1)
64007             .call(svgIcon('#operation-delete'));
64008
64009         wrap.append('button')
64010             .attr('class', 'modified-icon')
64011             .attr('tabindex', -1)
64012             .call(
64013                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
64014             );
64015
64016
64017         // Update
64018         fields = fields
64019             .merge(enter);
64020
64021         fields.selectAll('.form-label-button-wrap .remove-icon')
64022             .on('click', remove);
64023
64024         fields.selectAll('.modified-icon')
64025             .on('click', revert);
64026
64027         fields
64028             .order()
64029             .classed('modified', function(field) { return field.modified(); })
64030             .classed('present', function(field) { return field.present(); })
64031             .each(function(field) {
64032                 var reference = uiTagReference(field.reference || { key: field.key }, context);
64033
64034                 if (state === 'hover') {
64035                     reference.showing(false);
64036                 }
64037
64038                 select(this)
64039                     .call(field.input)
64040                     .selectAll('input')
64041                     .on('keydown', function() {
64042                         // if user presses enter, and combobox is not active, accept edits..
64043                         if (event.keyCode === 13 && select('.combobox').empty()) {
64044                             context.enter(modeBrowse(context));
64045                         }
64046                     })
64047                     .call(reference.body)
64048                     .select('.form-label-button-wrap')
64049                     .call(reference.button);
64050
64051                 field.input.tags(tags);
64052             });
64053
64054         notShown = notShown.map(function(field) {
64055             return {
64056                 title: field.label(),
64057                 value: field.label(),
64058                 field: field
64059             };
64060         });
64061
64062
64063         var more = selection$$1.selectAll('.more-fields')
64064             .data((notShown.length > 0) ? [0] : []);
64065
64066         more.exit()
64067             .remove();
64068
64069         more = more.enter()
64070             .append('div')
64071             .attr('class', 'more-fields')
64072             .append('label')
64073             .text(t('inspector.add_fields'))
64074             .merge(more);
64075
64076
64077         var input = more.selectAll('.value')
64078             .data([0]);
64079
64080         input.exit()
64081             .remove();
64082
64083         input = input.enter()
64084             .append('input')
64085             .attr('class', 'value')
64086             .attr('type', 'text')
64087             .call(utilNoAuto)
64088             .merge(input);
64089
64090         input
64091             .call(utilGetSetValue, '')
64092             .attr('placeholder', function() {
64093                 var placeholder = [];
64094                 for (var field in notShown) {
64095                     placeholder.push(notShown[field].title);
64096                 }
64097                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
64098             })
64099             .call(d3combobox().data(notShown)
64100                 .minItems(1)
64101                 .on('accept', show));
64102
64103
64104         function show(field) {
64105             field = field.field;
64106             field.show = true;
64107             content(selection$$1);
64108             field.input.focus();
64109         }
64110
64111
64112         function revert(field) {
64113             event.stopPropagation();
64114             event.preventDefault();
64115             dispatch$$1.call('change', field, field.revert());
64116         }
64117
64118
64119         function remove(field) {
64120             event.stopPropagation();
64121             event.preventDefault();
64122             dispatch$$1.call('change', field, field.remove());
64123         }
64124     }
64125
64126
64127     presets.preset = function(_) {
64128         if (!arguments.length) return preset;
64129         if (preset && preset.id === _.id) return presets;
64130         preset = _;
64131         fieldsArr = null;
64132         return presets;
64133     };
64134
64135
64136     presets.state = function(_) {
64137         if (!arguments.length) return state;
64138         state = _;
64139         return presets;
64140     };
64141
64142
64143     presets.tags = function(_) {
64144         if (!arguments.length) return tags;
64145         tags = _;
64146         // Don't reset fieldsArr here.
64147         return presets;
64148     };
64149
64150
64151     presets.entityID = function(_) {
64152         if (!arguments.length) return id;
64153         if (id === _) return presets;
64154         id = _;
64155         fieldsArr = null;
64156         return presets;
64157     };
64158
64159
64160     return utilRebind(presets, dispatch$$1, 'on');
64161 }
64162
64163 function uiEntityEditor(context) {
64164     var dispatch$$1 = dispatch('choose'),
64165         state = 'select',
64166         coalesceChanges = false,
64167         modified = false,
64168         base,
64169         id,
64170         activePreset,
64171         reference;
64172
64173     var presetEditor = uiPreset(context)
64174         .on('change', changeTags);
64175     var rawTagEditor = uiRawTagEditor(context)
64176         .on('change', changeTags);
64177
64178
64179     function entityEditor(selection$$1) {
64180         var entity = context.entity(id),
64181             tags = lodash.clone(entity.tags);
64182
64183         // Header
64184         var header = selection$$1.selectAll('.header')
64185             .data([0]);
64186
64187         // Enter
64188         var enter = header.enter()
64189             .append('div')
64190             .attr('class', 'header fillL cf');
64191
64192         enter
64193             .append('button')
64194             .attr('class', 'fl preset-reset preset-choose')
64195             .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
64196
64197         enter
64198             .append('button')
64199             .attr('class', 'fr preset-close')
64200             .on('click', function() { context.enter(modeBrowse(context)); })
64201             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
64202
64203         enter
64204             .append('h3')
64205             .text(t('inspector.edit'));
64206
64207         // Update
64208         header = header
64209             .merge(enter);
64210
64211         header.selectAll('.preset-reset')
64212             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64213
64214
64215         // Body
64216         var body = selection$$1.selectAll('.inspector-body')
64217             .data([0]);
64218
64219         // Enter
64220         enter = body.enter()
64221             .append('div')
64222             .attr('class', 'inspector-body');
64223
64224         enter
64225             .append('div')
64226             .attr('class', 'preset-list-item inspector-inner')
64227             .append('div')
64228             .attr('class', 'preset-list-button-wrap')
64229             .append('button')
64230             .attr('class', 'preset-list-button preset-reset')
64231             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
64232             .append('div')
64233             .attr('class', 'label');
64234
64235         enter
64236             .append('div')
64237             .attr('class', 'inspector-border inspector-preset');
64238
64239         enter
64240             .append('div')
64241             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
64242
64243         enter
64244             .append('div')
64245             .attr('class', 'inspector-border raw-member-editor inspector-inner');
64246
64247         enter
64248             .append('div')
64249             .attr('class', 'raw-membership-editor inspector-inner');
64250
64251         // Update
64252         body = body
64253             .merge(enter);
64254
64255         body.selectAll('.preset-list-button-wrap')
64256             .call(reference.button);
64257
64258         body.selectAll('.preset-list-item')
64259             .call(reference.body);
64260
64261         body.selectAll('.preset-reset')
64262             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64263
64264         body.select('.preset-list-item button')
64265             .call(uiPresetIcon()
64266                 .geometry(context.geometry(id))
64267                 .preset(activePreset));
64268
64269         body.select('.preset-list-item .label')
64270             .text(activePreset.name());
64271
64272         body.select('.inspector-preset')
64273             .call(presetEditor
64274                 .preset(activePreset)
64275                 .entityID(id)
64276                 .tags(tags)
64277                 .state(state));
64278
64279         body.select('.raw-tag-editor')
64280             .call(rawTagEditor
64281                 .preset(activePreset)
64282                 .entityID(id)
64283                 .tags(tags)
64284                 .state(state));
64285
64286         if (entity.type === 'relation') {
64287             body.select('.raw-member-editor')
64288                 .style('display', 'block')
64289                 .call(uiRawMemberEditor(context)
64290                     .entityID(id));
64291         } else {
64292             body.select('.raw-member-editor')
64293                 .style('display', 'none');
64294         }
64295
64296         body.select('.raw-membership-editor')
64297             .call(uiRawMembershipEditor(context)
64298                 .entityID(id));
64299
64300
64301         context.history()
64302             .on('change.entity-editor', historyChanged);
64303
64304
64305         function historyChanged() {
64306             if (state === 'hide') return;
64307
64308             var entity = context.hasEntity(id),
64309                 graph = context.graph();
64310             if (!entity) return;
64311
64312             entityEditor.preset(context.presets().match(entity, graph));
64313             entityEditor.modified(base !== graph);
64314             entityEditor(selection$$1);
64315         }
64316     }
64317
64318
64319     function clean(o) {
64320
64321         function cleanVal(k, v) {
64322             function keepSpaces(k) {
64323                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
64324                     'operating_times', 'smoking_hours', 'happy_hours'];
64325                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
64326             }
64327
64328             var blacklist = ['description', 'note', 'fixme'];
64329             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
64330
64331             var cleaned = v.split(';')
64332                 .map(function(s) { return s.trim(); })
64333                 .join(keepSpaces(k) ? '; ' : ';');
64334
64335             // The code below is not intended to validate websites and emails.
64336             // It is only intended to prevent obvious copy-paste errors. (#2323)
64337
64338             // clean website- and email-like tags
64339             if (k.indexOf('website') !== -1 ||
64340                 k.indexOf('email') !== -1 ||
64341                 cleaned.indexOf('http') === 0) {
64342                 cleaned = cleaned
64343                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
64344
64345             }
64346
64347             return cleaned;
64348         }
64349
64350         var out = {}, k, v;
64351         for (k in o) {
64352             if (k && (v = o[k]) !== undefined) {
64353                 out[k] = cleanVal(k, v);
64354             }
64355         }
64356         return out;
64357     }
64358
64359
64360     // Tag changes that fire on input can all get coalesced into a single
64361     // history operation when the user leaves the field.  #2342
64362     function changeTags(changed, onInput) {
64363         var entity = context.entity(id),
64364             annotation = t('operations.change_tags.annotation'),
64365             tags = lodash.clone(entity.tags);
64366
64367         lodash.forEach(changed, function(v, k) {
64368             if (v !== undefined || tags.hasOwnProperty(k)) {
64369                 tags[k] = v;
64370             }
64371         });
64372
64373         if (!onInput) {
64374             tags = clean(tags);
64375         }
64376
64377         if (!lodash.isEqual(entity.tags, tags)) {
64378             if (coalesceChanges) {
64379                 context.overwrite(actionChangeTags(id, tags), annotation);
64380             } else {
64381                 context.perform(actionChangeTags(id, tags), annotation);
64382                 coalesceChanges = !!onInput;
64383             }
64384         }
64385     }
64386
64387
64388     entityEditor.modified = function(_) {
64389         if (!arguments.length) return modified;
64390         modified = _;
64391         selectAll('button.preset-close use')
64392             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
64393     };
64394
64395
64396     entityEditor.state = function(_) {
64397         if (!arguments.length) return state;
64398         state = _;
64399         return entityEditor;
64400     };
64401
64402
64403     entityEditor.entityID = function(_) {
64404         if (!arguments.length) return id;
64405         id = _;
64406         base = context.graph();
64407         entityEditor.preset(context.presets().match(context.entity(id), base));
64408         entityEditor.modified(false);
64409         coalesceChanges = false;
64410         return entityEditor;
64411     };
64412
64413
64414     entityEditor.preset = function(_) {
64415         if (!arguments.length) return activePreset;
64416         if (_ !== activePreset) {
64417             activePreset = _;
64418             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
64419                 .showing(false);
64420         }
64421         return entityEditor;
64422     };
64423
64424
64425     return utilRebind(entityEditor, dispatch$$1, 'on');
64426 }
64427
64428 function uiPresetList(context) {
64429     var dispatch$$1 = dispatch('choose'),
64430         id,
64431         currentPreset,
64432         autofocus = false;
64433
64434
64435     function presetList(selection$$1) {
64436         var entity = context.entity(id),
64437             geometry = context.geometry(id);
64438
64439         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
64440         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
64441             geometry = 'point';
64442         }
64443
64444         var presets = context.presets().matchGeometry(geometry);
64445
64446         selection$$1.html('');
64447
64448         var messagewrap = selection$$1
64449             .append('div')
64450             .attr('class', 'header fillL cf');
64451
64452         var message = messagewrap
64453             .append('h3')
64454             .text(t('inspector.choose'));
64455
64456         if (context.entity(id).isUsed(context.graph())) {
64457             messagewrap
64458                 .append('button')
64459                 .attr('class', 'preset-choose')
64460                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
64461                 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
64462         } else {
64463             messagewrap
64464                 .append('button')
64465                 .attr('class', 'close')
64466                 .on('click', function() {
64467                     context.enter(modeBrowse(context));
64468                 })
64469                 .call(svgIcon('#icon-close'));
64470         }
64471
64472         function keydown() {
64473             // hack to let delete shortcut work when search is autofocused
64474             if (search.property('value').length === 0 &&
64475                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
64476                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
64477                 event.preventDefault();
64478                 event.stopPropagation();
64479                 operationDelete([id], context)();
64480             } else if (search.property('value').length === 0 &&
64481                 (event.ctrlKey || event.metaKey) &&
64482                 event.keyCode === d3keybinding.keyCodes.z) {
64483                 event.preventDefault();
64484                 event.stopPropagation();
64485                 context.undo();
64486             } else if (!event.ctrlKey && !event.metaKey) {
64487                 select(this).on('keydown', null);
64488             }
64489         }
64490
64491         function keypress() {
64492             // enter
64493             var value = search.property('value');
64494             if (event.keyCode === 13 && value.length) {
64495                 list.selectAll('.preset-list-item:first-child').datum().choose();
64496             }
64497         }
64498
64499         function inputevent() {
64500             var value = search.property('value');
64501             list.classed('filtered', value.length);
64502             if (value.length) {
64503                 var results = presets.search(value, geometry);
64504                 message.text(t('inspector.results', {
64505                     n: results.collection.length,
64506                     search: value
64507                 }));
64508                 list.call(drawList, results);
64509             } else {
64510                 list.call(drawList, context.presets().defaults(geometry, 36));
64511                 message.text(t('inspector.choose'));
64512             }
64513         }
64514
64515         var searchWrap = selection$$1
64516             .append('div')
64517             .attr('class', 'search-header');
64518
64519         var search = searchWrap
64520             .append('input')
64521             .attr('class', 'preset-search-input')
64522             .attr('placeholder', t('inspector.search'))
64523             .attr('type', 'search')
64524             .call(utilNoAuto)
64525             .on('keydown', keydown)
64526             .on('keypress', keypress)
64527             .on('input', inputevent);
64528
64529         searchWrap
64530             .call(svgIcon('#icon-search', 'pre-text'));
64531
64532         if (autofocus) {
64533             search.node().focus();
64534         }
64535
64536         var listWrap = selection$$1
64537             .append('div')
64538             .attr('class', 'inspector-body');
64539
64540         var list = listWrap
64541             .append('div')
64542             .attr('class', 'preset-list fillL cf')
64543             .call(drawList, context.presets().defaults(geometry, 36));
64544     }
64545
64546
64547     function drawList(list, presets) {
64548         var collection = presets.collection.map(function(preset) {
64549             return preset.members ? CategoryItem(preset) : PresetItem(preset);
64550         });
64551
64552         var items = list.selectAll('.preset-list-item')
64553             .data(collection, function(d) { return d.preset.id; });
64554
64555         items.order();
64556
64557         items.exit()
64558             .remove();
64559
64560         items.enter()
64561             .append('div')
64562             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
64563             .classed('current', function(item) { return item.preset === currentPreset; })
64564             .each(function(item) { select(this).call(item); })
64565             .style('opacity', 0)
64566             .transition()
64567             .style('opacity', 1);
64568     }
64569
64570
64571     function CategoryItem(preset) {
64572         var box, sublist, shown = false;
64573
64574         function item(selection$$1) {
64575             var wrap = selection$$1.append('div')
64576                 .attr('class', 'preset-list-button-wrap category col12');
64577
64578             var button = wrap
64579                 .append('button')
64580                 .attr('class', 'preset-list-button')
64581                 .classed('expanded', false)
64582                 .call(uiPresetIcon()
64583                     .geometry(context.geometry(id))
64584                     .preset(preset))
64585                 .on('click', function() {
64586                     var isExpanded = select(this).classed('expanded');
64587                     var iconName = isExpanded ?
64588                         (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
64589                     select(this)
64590                         .classed('expanded', !isExpanded);
64591                     select(this).selectAll('div.label svg.icon use')
64592                         .attr('href', iconName);
64593                     item.choose();
64594                 });
64595
64596             var label = button
64597                 .append('div')
64598                 .attr('class', 'label');
64599
64600             label
64601                 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
64602                 .append('span')
64603                 .html(function() { return preset.name() + '&hellip;'; });
64604
64605             box = selection$$1.append('div')
64606                 .attr('class', 'subgrid col12')
64607                 .style('max-height', '0px')
64608                 .style('opacity', 0);
64609
64610             box.append('div')
64611                 .attr('class', 'arrow');
64612
64613             sublist = box.append('div')
64614                 .attr('class', 'preset-list fillL3 cf fl');
64615         }
64616
64617
64618         item.choose = function() {
64619             if (!box || !sublist) return;
64620
64621             if (shown) {
64622                 shown = false;
64623                 box.transition()
64624                     .duration(200)
64625                     .style('opacity', '0')
64626                     .style('max-height', '0px')
64627                     .style('padding-bottom', '0px');
64628             } else {
64629                 shown = true;
64630                 sublist.call(drawList, preset.members);
64631                 box.transition()
64632                     .duration(200)
64633                     .style('opacity', '1')
64634                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
64635                     .style('padding-bottom', '20px');
64636             }
64637         };
64638
64639         item.preset = preset;
64640
64641         return item;
64642     }
64643
64644
64645     function PresetItem(preset) {
64646         function item(selection$$1) {
64647             var wrap = selection$$1.append('div')
64648                 .attr('class', 'preset-list-button-wrap col12');
64649
64650             wrap.append('button')
64651                 .attr('class', 'preset-list-button')
64652                 .call(uiPresetIcon()
64653                     .geometry(context.geometry(id))
64654                     .preset(preset))
64655                 .on('click', item.choose)
64656                 .append('div')
64657                 .attr('class', 'label')
64658                 .text(preset.name());
64659
64660             wrap.call(item.reference.button);
64661             selection$$1.call(item.reference.body);
64662         }
64663
64664         item.choose = function() {
64665             context.presets().choose(preset);
64666
64667             context.perform(
64668                 actionChangePreset(id, currentPreset, preset),
64669                 t('operations.change_tags.annotation')
64670             );
64671
64672             dispatch$$1.call('choose', this, preset);
64673         };
64674
64675         item.help = function() {
64676             event.stopPropagation();
64677             item.reference.toggle();
64678         };
64679
64680         item.preset = preset;
64681         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
64682
64683         return item;
64684     }
64685
64686
64687     presetList.autofocus = function(_) {
64688         if (!arguments.length) return autofocus;
64689         autofocus = _;
64690         return presetList;
64691     };
64692
64693
64694     presetList.entityID = function(_) {
64695         if (!arguments.length) return id;
64696         id = _;
64697         presetList.preset(context.presets().match(context.entity(id), context.graph()));
64698         return presetList;
64699     };
64700
64701
64702     presetList.preset = function(_) {
64703         if (!arguments.length) return currentPreset;
64704         currentPreset = _;
64705         return presetList;
64706     };
64707
64708
64709     return utilRebind(presetList, dispatch$$1, 'on');
64710 }
64711
64712 function uiViewOnOSM(context) {
64713     var id;
64714
64715     function viewOnOSM(selection) {
64716         var entity = context.entity(id);
64717
64718         selection.style('display', entity.isNew() ? 'none' : null);
64719
64720         var link = selection.selectAll('.view-on-osm')
64721             .data([0]);
64722
64723         var enter = link.enter()
64724             .append('a')
64725             .attr('class', 'view-on-osm')
64726             .attr('target', '_blank')
64727             .call(svgIcon('#icon-out-link', 'inline'));
64728
64729         enter
64730             .append('span')
64731             .text(t('inspector.view_on_osm'));
64732
64733         link
64734             .merge(enter)
64735             .attr('href', context.connection().entityURL(entity));
64736     }
64737
64738
64739     viewOnOSM.entityID = function(_) {
64740         if (!arguments.length) return id;
64741         id = _;
64742         return viewOnOSM;
64743     };
64744
64745     return viewOnOSM;
64746 }
64747
64748 function uiInspector(context) {
64749     var presetList = uiPresetList(context),
64750         entityEditor = uiEntityEditor(context),
64751         state = 'select',
64752         entityID,
64753         newFeature = false;
64754
64755
64756     function inspector(selection$$1) {
64757         presetList
64758             .entityID(entityID)
64759             .autofocus(newFeature)
64760             .on('choose', setPreset);
64761
64762         entityEditor
64763             .state(state)
64764             .entityID(entityID)
64765             .on('choose', showList);
64766
64767         var wrap = selection$$1.selectAll('.panewrap')
64768             .data([0]);
64769
64770         var enter = wrap.enter()
64771             .append('div')
64772             .attr('class', 'panewrap');
64773
64774         enter
64775             .append('div')
64776             .attr('class', 'preset-list-pane pane');
64777
64778         enter
64779             .append('div')
64780             .attr('class', 'entity-editor-pane pane');
64781
64782         wrap = wrap.merge(enter);
64783         var presetPane = wrap.selectAll('.preset-list-pane');
64784         var editorPane = wrap.selectAll('.entity-editor-pane');
64785
64786         var graph = context.graph(),
64787             entity = context.entity(entityID),
64788             showEditor = state === 'hover' ||
64789                 entity.isUsed(graph) ||
64790                 entity.isHighwayIntersection(graph);
64791
64792         if (showEditor) {
64793             wrap.style('right', '0%');
64794             editorPane.call(entityEditor);
64795         } else {
64796             wrap.style('right', '-100%');
64797             presetPane.call(presetList);
64798         }
64799
64800         var footer = selection$$1.selectAll('.footer')
64801             .data([0]);
64802
64803         footer = footer.enter()
64804             .append('div')
64805             .attr('class', 'footer')
64806             .merge(footer);
64807
64808         footer
64809             .call(uiViewOnOSM(context).entityID(entityID));
64810
64811
64812         function showList(preset) {
64813             wrap.transition()
64814                 .styleTween('right', function() { return value$1('0%', '-100%'); });
64815
64816             presetPane
64817                 .call(presetList.preset(preset).autofocus(true));
64818         }
64819
64820
64821         function setPreset(preset) {
64822             wrap.transition()
64823                 .styleTween('right', function() { return value$1('-100%', '0%'); });
64824
64825             editorPane
64826                 .call(entityEditor.preset(preset));
64827         }
64828     }
64829
64830
64831     inspector.state = function(_) {
64832         if (!arguments.length) return state;
64833         state = _;
64834         entityEditor.state(state);
64835         return inspector;
64836     };
64837
64838
64839     inspector.entityID = function(_) {
64840         if (!arguments.length) return entityID;
64841         entityID = _;
64842         return inspector;
64843     };
64844
64845
64846     inspector.newFeature = function(_) {
64847         if (!arguments.length) return newFeature;
64848         newFeature = _;
64849         return inspector;
64850     };
64851
64852
64853     return inspector;
64854 }
64855
64856 function uiNotice(context) {
64857
64858     return function(selection) {
64859         var div = selection
64860             .append('div')
64861             .attr('class', 'notice');
64862
64863         var button = div
64864             .append('button')
64865             .attr('class', 'zoom-to notice')
64866             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
64867
64868         button
64869             .call(svgIcon('#icon-plus', 'pre-text'))
64870             .append('span')
64871             .attr('class', 'label')
64872             .text(t('zoom_in_edit'));
64873
64874
64875         function disableTooHigh() {
64876             div.style('display', context.editable() ? 'none' : 'block');
64877         }
64878
64879         context.map()
64880             .on('move.notice', lodash.debounce(disableTooHigh, 500));
64881
64882         disableTooHigh();
64883     };
64884 }
64885
64886 function uiSidebar(context) {
64887     var inspector = uiInspector(context),
64888         current;
64889
64890
64891     function sidebar(selection) {
64892         var featureListWrap = selection
64893             .append('div')
64894             .attr('class', 'feature-list-pane')
64895             .call(uiFeatureList(context));
64896
64897         selection
64898             .call(uiNotice(context));
64899
64900         var inspectorWrap = selection
64901             .append('div')
64902             .attr('class', 'inspector-hidden inspector-wrap fr');
64903
64904
64905         function hover(id) {
64906             if (!current && context.hasEntity(id)) {
64907                 featureListWrap
64908                     .classed('inspector-hidden', true);
64909
64910                 inspectorWrap
64911                     .classed('inspector-hidden', false)
64912                     .classed('inspector-hover', true);
64913
64914                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
64915                     inspector
64916                         .state('hover')
64917                         .entityID(id);
64918
64919                     inspectorWrap
64920                         .call(inspector);
64921                 }
64922
64923             } else if (!current) {
64924                 featureListWrap
64925                     .classed('inspector-hidden', false);
64926                 inspectorWrap
64927                     .classed('inspector-hidden', true);
64928                 inspector
64929                     .state('hide');
64930             }
64931         }
64932
64933
64934         sidebar.hover = lodash.throttle(hover, 200);
64935
64936
64937         sidebar.select = function(id, newFeature) {
64938             if (!current && id) {
64939                 featureListWrap
64940                     .classed('inspector-hidden', true);
64941
64942                 inspectorWrap
64943                     .classed('inspector-hidden', false)
64944                     .classed('inspector-hover', false);
64945
64946                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
64947                     inspector
64948                         .state('select')
64949                         .entityID(id)
64950                         .newFeature(newFeature);
64951
64952                     inspectorWrap
64953                         .call(inspector);
64954                 }
64955
64956             } else if (!current) {
64957                 featureListWrap
64958                     .classed('inspector-hidden', false);
64959                 inspectorWrap
64960                     .classed('inspector-hidden', true);
64961                 inspector
64962                     .state('hide');
64963             }
64964         };
64965
64966
64967         sidebar.show = function(component) {
64968             featureListWrap
64969                 .classed('inspector-hidden', true);
64970             inspectorWrap
64971                 .classed('inspector-hidden', true);
64972
64973             if (current) current.remove();
64974             current = selection
64975                 .append('div')
64976                 .attr('class', 'sidebar-component')
64977                 .call(component);
64978         };
64979
64980
64981         sidebar.hide = function() {
64982             featureListWrap
64983                 .classed('inspector-hidden', false);
64984             inspectorWrap
64985                 .classed('inspector-hidden', true);
64986
64987             if (current) current.remove();
64988             current = null;
64989         };
64990     }
64991
64992
64993     sidebar.hover = function() {};
64994     sidebar.hover.cancel = function() {};
64995     sidebar.select = function() {};
64996     sidebar.show = function() {};
64997     sidebar.hide = function() {};
64998
64999     return sidebar;
65000 }
65001
65002 function uiSpinner(context) {
65003     var connection = context.connection();
65004
65005
65006     return function(selection) {
65007         var img = selection
65008             .append('img')
65009             .attr('src', context.imagePath('loader-black.gif'))
65010             .style('opacity', 0);
65011
65012         connection
65013             .on('loading.spinner', function() {
65014                 img.transition()
65015                     .style('opacity', 1);
65016             });
65017
65018         connection
65019             .on('loaded.spinner', function() {
65020                 img.transition()
65021                     .style('opacity', 0);
65022             });
65023     };
65024 }
65025
65026 function uiSplash(context) {
65027
65028     return function(selection$$1) {
65029         if (context.storage('sawSplash'))
65030              return;
65031
65032         context.storage('sawSplash', true);
65033
65034         var modalSelection = uiModal(selection$$1);
65035
65036         modalSelection.select('.modal')
65037             .attr('class', 'modal-splash modal col6');
65038
65039         var introModal = modalSelection.select('.content')
65040             .append('div')
65041             .attr('class', 'fillL');
65042
65043         introModal
65044             .append('div')
65045             .attr('class','modal-section cf')
65046             .append('h3').text(t('splash.welcome'));
65047
65048         introModal
65049             .append('div')
65050             .attr('class','modal-section')
65051             .append('p')
65052             .html(t('splash.text', {
65053                 version: context.version,
65054                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
65055                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
65056             }));
65057
65058         var buttons = introModal
65059             .append('div')
65060             .attr('class', 'modal-actions cf');
65061
65062         buttons
65063             .append('button')
65064             .attr('class', 'col6 walkthrough')
65065             .text(t('splash.walkthrough'))
65066             .on('click', function() {
65067                 select(document.body).call(uiIntro(context));
65068                 modalSelection.close();
65069             });
65070
65071         buttons
65072             .append('button')
65073             .attr('class', 'col6 start')
65074             .text(t('splash.start'))
65075             .on('click', modalSelection.close);
65076
65077         modalSelection.select('button.close')
65078             .attr('class','hide');
65079
65080     };
65081 }
65082
65083 function uiStatus(context) {
65084     var connection = context.connection();
65085
65086     return function(selection$$1) {
65087
65088         function update() {
65089             connection.status(function(err, apiStatus) {
65090                 selection$$1.html('');
65091
65092                 if (err) {
65093                     if (apiStatus === 'rateLimited') {
65094                         selection$$1
65095                             .text(t('status.rateLimit'))
65096                             .append('a')
65097                             .attr('class', 'api-status-login')
65098                             .attr('target', '_blank')
65099                             .call(svgIcon('#icon-out-link', 'inline'))
65100                             .append('span')
65101                             .text(t('login'))
65102                             .on('click.login', function() {
65103                                 event.preventDefault();
65104                                 connection.authenticate();
65105                             });
65106                     } else {
65107                         // TODO: nice messages for different error types
65108                         selection$$1.text(t('status.error'));
65109                     }
65110
65111                 } else if (apiStatus === 'readonly') {
65112                     selection$$1.text(t('status.readonly'));
65113                 } else if (apiStatus === 'offline') {
65114                     selection$$1.text(t('status.offline'));
65115                 }
65116
65117                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
65118             });
65119         }
65120
65121         connection
65122             .on('change', function() { update(selection$$1); });
65123
65124         window.setInterval(update, 90000);
65125         update(selection$$1);
65126     };
65127 }
65128
65129 function uiUndoRedo(context) {
65130     var commands = [{
65131         id: 'undo',
65132         cmd: uiCmd('⌘Z'),
65133         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
65134         annotation: function() { return context.history().undoAnnotation(); }
65135     }, {
65136         id: 'redo',
65137         cmd: uiCmd('⌘⇧Z'),
65138         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
65139         annotation: function() { return context.history().redoAnnotation(); }
65140     }];
65141
65142
65143     function saving() {
65144         return context.mode().id === 'save';
65145     }
65146
65147
65148     return function(selection$$1) {
65149         var tooltipBehavior = tooltip()
65150             .placement('bottom')
65151             .html(true)
65152             .title(function (d) {
65153                 return uiTooltipHtml(d.annotation() ?
65154                     t(d.id + '.tooltip', {action: d.annotation()}) :
65155                     t(d.id + '.nothing'), d.cmd);
65156             });
65157
65158         var buttons = selection$$1.selectAll('button')
65159             .data(commands)
65160             .enter()
65161             .append('button')
65162             .attr('class', 'col6 disabled')
65163             .on('click', function(d) { return d.action(); })
65164             .call(tooltipBehavior);
65165
65166         buttons.each(function(d) {
65167             var iconName = d.id;
65168             if (textDirection === 'rtl') {
65169                 if (iconName === 'undo') {
65170                     iconName = 'redo';
65171                 } else if (iconName === 'redo') {
65172                     iconName = 'undo';
65173                 }
65174             }
65175             select(this)
65176                 .call(svgIcon('#icon-' + iconName));
65177         });
65178
65179         var keybinding = d3keybinding('undo')
65180             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
65181             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
65182
65183         select(document)
65184             .call(keybinding);
65185
65186         context.history()
65187             .on('change.undo_redo', update);
65188
65189         context
65190             .on('enter.undo_redo', update);
65191
65192         function update() {
65193             buttons
65194                 .property('disabled', saving())
65195                 .classed('disabled', function(d) { return !d.annotation(); })
65196                 .each(function() {
65197                     var selection$$1 = select(this);
65198                     if (selection$$1.property('tooltipVisible')) {
65199                         selection$$1.call(tooltipBehavior.show);
65200                     }
65201                 });
65202         }
65203     };
65204 }
65205
65206 function uiZoom(context) {
65207     var zooms = [{
65208         id: 'zoom-in',
65209         icon: 'plus',
65210         title: t('zoom.in'),
65211         action: context.zoomIn,
65212         key: '+'
65213     }, {
65214         id: 'zoom-out',
65215         icon: 'minus',
65216         title: t('zoom.out'),
65217         action: context.zoomOut,
65218         key: '-'
65219     }];
65220
65221
65222     function zoomIn() {
65223         event.preventDefault();
65224         if (!context.inIntro()) context.zoomIn();
65225     }
65226
65227
65228     function zoomOut() {
65229         event.preventDefault();
65230         if (!context.inIntro()) context.zoomOut();
65231     }
65232
65233
65234     function zoomInFurther() {
65235         event.preventDefault();
65236         if (!context.inIntro()) context.zoomInFurther();
65237     }
65238
65239
65240     function zoomOutFurther() {
65241         event.preventDefault();
65242         if (!context.inIntro()) context.zoomOutFurther();
65243     }
65244
65245
65246     return function(selection$$1) {
65247         var button = selection$$1.selectAll('button')
65248             .data(zooms)
65249             .enter()
65250             .append('button')
65251             .attr('tabindex', -1)
65252             .attr('class', function(d) { return d.id; })
65253             .on('click.editor', function(d) { d.action(); })
65254             .call(tooltip()
65255                 .placement((textDirection === 'rtl') ? 'right' : 'left')
65256                 .html(true)
65257                 .title(function(d) {
65258                     return uiTooltipHtml(d.title, d.key);
65259                 })
65260             );
65261
65262         button.each(function(d) {
65263             select(this)
65264                 .call(svgIcon('#icon-' + d.icon, 'light'));
65265         });
65266
65267         var keybinding = d3keybinding('zoom');
65268
65269         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
65270             keybinding.on([key, '⇧' + key], zoomIn);
65271             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
65272         });
65273         lodash.each(['-','ffminus','dash'], function(key) {
65274             keybinding.on([key, '⇧' + key], zoomOut);
65275             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
65276         });
65277
65278         select(document)
65279             .call(keybinding);
65280     };
65281 }
65282
65283 function uiInit(context) {
65284     var uiInitCounter = 0;
65285
65286
65287     function render(container) {
65288         container
65289             .attr('dir', textDirection);
65290
65291         var map$$1 = context.map();
65292
65293         var hash = behaviorHash(context);
65294         hash();
65295
65296         if (!hash.hadHash) {
65297             map$$1.centerZoom([0, 0], 2);
65298         }
65299
65300         container
65301             .append('svg')
65302             .attr('id', 'defs')
65303             .call(svgDefs(context));
65304
65305         container
65306             .append('div')
65307             .attr('id', 'sidebar')
65308             .attr('class', 'col4')
65309             .call(ui.sidebar);
65310
65311         var content = container
65312             .append('div')
65313             .attr('id', 'content')
65314             .attr('class', 'active');
65315
65316         var bar = content
65317             .append('div')
65318             .attr('id', 'bar')
65319             .attr('class', 'fillD');
65320
65321         content
65322             .append('div')
65323             .attr('id', 'map')
65324             .attr('dir', 'ltr')
65325             .call(map$$1);
65326
65327         content
65328             .call(uiMapInMap(context));
65329
65330         content
65331             .append('div')
65332             .call(uiInfo(context));
65333
65334         bar
65335             .append('div')
65336             .attr('class', 'spacer col4');
65337
65338         var limiter = bar.append('div')
65339             .attr('class', 'limiter');
65340
65341         limiter
65342             .append('div')
65343             .attr('class', 'button-wrap joined col3')
65344             .call(uiModes(context), limiter);
65345
65346         limiter
65347             .append('div')
65348             .attr('class', 'button-wrap joined col1')
65349             .call(uiUndoRedo(context));
65350
65351         limiter
65352             .append('div')
65353             .attr('class', 'button-wrap col1')
65354             .call(uiSave(context));
65355
65356         bar
65357             .append('div')
65358             .attr('class', 'full-screen')
65359             .call(uiFullScreen(context));
65360
65361         bar
65362             .append('div')
65363             .attr('class', 'spinner')
65364             .call(uiSpinner(context));
65365
65366         var controls = bar
65367             .append('div')
65368             .attr('class', 'map-controls');
65369
65370         controls
65371             .append('div')
65372             .attr('class', 'map-control zoombuttons')
65373             .call(uiZoom(context));
65374
65375         controls
65376             .append('div')
65377             .attr('class', 'map-control geolocate-control')
65378             .call(uiGeolocate(context));
65379
65380         controls
65381             .append('div')
65382             .attr('class', 'map-control background-control')
65383             .call(uiBackground(context));
65384
65385         controls
65386             .append('div')
65387             .attr('class', 'map-control map-data-control')
65388             .call(uiMapData(context));
65389
65390         controls
65391             .append('div')
65392             .attr('class', 'map-control help-control')
65393             .call(uiHelp(context));
65394
65395         var about = content
65396             .append('div')
65397             .attr('id', 'about');
65398
65399         about
65400             .append('div')
65401             .attr('id', 'attrib')
65402             .attr('dir', 'ltr')
65403             .call(uiAttribution(context));
65404
65405         var footer = about
65406             .append('div')
65407             .attr('id', 'footer')
65408             .attr('class', 'fillD');
65409
65410         footer
65411             .append('div')
65412             .attr('class', 'api-status')
65413             .call(uiStatus(context));
65414
65415         footer
65416             .append('div')
65417             .attr('id', 'scale-block')
65418             .call(uiScale(context));
65419
65420         var aboutList = footer
65421             .append('div')
65422             .attr('id', 'info-block')
65423             .append('ul')
65424             .attr('id', 'about-list');
65425
65426         if (!context.embed()) {
65427             aboutList.call(uiAccount(context));
65428         }
65429
65430         aboutList
65431             .append('li')
65432             .append('a')
65433             .attr('target', '_blank')
65434             .attr('tabindex', -1)
65435             .attr('href', 'https://github.com/openstreetmap/iD')
65436             .text(context.version);
65437
65438         var issueLinks = aboutList
65439             .append('li');
65440
65441         issueLinks
65442             .append('a')
65443             .attr('target', '_blank')
65444             .attr('tabindex', -1)
65445             .attr('href', 'https://github.com/openstreetmap/iD/issues')
65446             .call(svgIcon('#icon-bug', 'light'))
65447             .call(tooltip().title(t('report_a_bug')).placement('top'));
65448
65449         issueLinks
65450             .append('a')
65451             .attr('target', '_blank')
65452             .attr('tabindex', -1)
65453             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
65454             .call(svgIcon('#icon-translate', 'light'))
65455             .call(tooltip().title(t('help_translate')).placement('top'));
65456
65457         aboutList
65458             .append('li')
65459             .attr('class', 'feature-warning')
65460             .attr('tabindex', -1)
65461             .call(uiFeatureInfo(context));
65462
65463         aboutList
65464             .append('li')
65465             .attr('class', 'user-list')
65466             .attr('tabindex', -1)
65467             .call(uiContributors(context));
65468
65469
65470         window.onbeforeunload = function() {
65471             return context.save();
65472         };
65473
65474         window.onunload = function() {
65475             context.history().unlock();
65476         };
65477
65478         var mapDimensions = map$$1.dimensions();
65479
65480
65481         function onResize() {
65482             mapDimensions = utilGetDimensions(content, true);
65483             map$$1.dimensions(mapDimensions);
65484         }
65485
65486         select(window)
65487             .on('resize.editor', onResize);
65488
65489         onResize();
65490
65491         function pan(d) {
65492             return function() {
65493                 event.preventDefault();
65494                 if (!context.inIntro()) {
65495                     context.pan(d, 100);
65496                 }
65497             };
65498         }
65499
65500
65501         // pan amount
65502         var pa = 10;
65503
65504         var keybinding = d3keybinding('main')
65505             .on('⌫', function() { event.preventDefault(); })
65506             .on('←', pan([pa, 0]))
65507             .on('↑', pan([0, pa]))
65508             .on('→', pan([-pa, 0]))
65509             .on('↓', pan([0, -pa]))
65510             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
65511             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
65512             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
65513             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
65514
65515         select(document)
65516             .call(keybinding);
65517
65518         context.enter(modeBrowse(context));
65519
65520         if (!uiInitCounter++) {
65521             context.container()
65522                 .call(uiSplash(context))
65523                 .call(uiRestore(context));
65524         }
65525
65526         var authenticating = uiLoading(context)
65527             .message(t('loading_auth'))
65528             .blocking(true);
65529
65530         context.connection()
65531             .on('authLoading.ui', function() {
65532                 context.container()
65533                     .call(authenticating);
65534             })
65535             .on('authDone.ui', function() {
65536                 authenticating.close();
65537             });
65538
65539         uiInitCounter++;
65540     }
65541
65542
65543     var renderCallback;
65544
65545     function ui(node, callback) {
65546         renderCallback = callback;
65547         var container = select(node);
65548         context.container(container);
65549         context.loadLocale(function(err) {
65550             if (!err) {
65551                 render(container);
65552             }
65553             if (callback) {
65554                 callback(err);
65555             }
65556         });
65557     }
65558
65559
65560     ui.restart = function(arg) {
65561         context.locale(arg);
65562         context.loadLocale(function(err) {
65563             if (!err) {
65564                 context.container().selectAll('*').remove();
65565                 render(context.container());
65566                 if (renderCallback) renderCallback();
65567             }
65568         });
65569     };
65570
65571
65572     ui.sidebar = uiSidebar(context);
65573
65574     return ui;
65575 }
65576
65577 function uiCommit(context) {
65578     var dispatch$$1 = dispatch('cancel', 'save');
65579
65580
65581     function commit(selection$$1) {
65582         var changes = context.history().changes(),
65583             summary = context.history().difference().summary();
65584
65585         selection$$1
65586             .append('div')
65587             .attr('class', 'header fillL')
65588             .append('h3')
65589             .text(t('commit.title'));
65590
65591         var body = selection$$1
65592             .append('div')
65593             .attr('class', 'body');
65594
65595         var commentSection = body
65596             .append('div')
65597             .attr('class', 'modal-section form-field commit-form');
65598
65599         commentSection
65600             .append('label')
65601             .attr('class', 'form-label')
65602             .text(t('commit.message_label'));
65603
65604         var commentField = commentSection
65605             .append('textarea')
65606             .attr('placeholder', t('commit.description_placeholder'))
65607             .attr('maxlength', 255)
65608             .property('value', context.storage('comment') || '')
65609             .on('input.save', checkComment)
65610             .on('change.save', checkComment)
65611             .on('blur.save', function() {
65612                 context.storage('comment', this.value);
65613             });
65614
65615
65616         commentField.node().select();
65617
65618         context.connection().userChangesets(function (err, changesets) {
65619             if (err) return;
65620
65621             var comments = changesets.map(function(changeset) {
65622                 return {
65623                     title: changeset.tags.comment,
65624                     value: changeset.tags.comment
65625                 };
65626             });
65627
65628             commentField
65629                 .call(d3combobox()
65630                     .caseSensitive(true)
65631                     .data(lodash.uniqBy(comments, 'title'))
65632                 );
65633         });
65634
65635         var clippyArea = commentSection.append('div')
65636             .attr('class', 'clippy-area');
65637
65638         var changeSetInfo = commentSection.append('div')
65639             .attr('class', 'changeset-info');
65640
65641         changeSetInfo.append('a')
65642             .attr('target', '_blank')
65643             .attr('tabindex', -1)
65644             .call(svgIcon('#icon-out-link', 'inline'))
65645             .attr('href', t('commit.about_changeset_comments_link'))
65646             .append('span')
65647             .text(t('commit.about_changeset_comments'));
65648
65649
65650         // Warnings
65651         var warnings = body.selectAll('div.warning-section')
65652             .data([context.history().validate(changes)]);
65653
65654         warnings = warnings.enter()
65655             .append('div')
65656             .attr('class', 'modal-section warning-section fillL2')
65657             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
65658             .style('background', '#ffb')
65659             .merge(warnings);
65660
65661         warnings
65662             .append('h3')
65663             .text(t('commit.warnings'));
65664
65665         warnings
65666             .append('ul')
65667             .attr('class', 'changeset-list');
65668
65669         var warningLi = warnings.select('ul').selectAll('li')
65670             .data(function(d) { return d; });
65671
65672         warningLi = warningLi.enter()
65673             .append('li')
65674             .on('mouseover', mouseover)
65675             .on('mouseout', mouseout)
65676             .on('click', warningClick)
65677             .merge(warningLi);
65678
65679         warningLi
65680             .call(svgIcon('#icon-alert', 'pre-text'));
65681
65682         warningLi
65683             .append('strong')
65684             .text(function(d) { return d.message; });
65685
65686         warningLi.filter(function(d) { return d.tooltip; })
65687             .call(tooltip()
65688                 .title(function(d) { return d.tooltip; })
65689                 .placement('top')
65690             );
65691
65692
65693         // Upload Explanation
65694         var saveSection = body
65695             .append('div')
65696             .attr('class','modal-section save-section fillL cf');
65697
65698         var prose = saveSection
65699             .append('p')
65700             .attr('class', 'commit-info')
65701             .html(t('commit.upload_explanation'));
65702
65703
65704         context.connection().userDetails(function(err, user) {
65705             if (err) return;
65706
65707             var userLink = select(document.createElement('div'));
65708
65709             if (user.image_url) {
65710                 userLink
65711                     .append('img')
65712                     .attr('src', user.image_url)
65713                     .attr('class', 'icon pre-text user-icon');
65714             }
65715
65716             userLink
65717                 .append('a')
65718                 .attr('class','user-info')
65719                 .text(user.display_name)
65720                 .attr('href', context.connection().userURL(user.display_name))
65721                 .attr('tabindex', -1)
65722                 .attr('target', '_blank');
65723
65724             prose
65725                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
65726         });
65727
65728
65729         // Buttons
65730         var buttonSection = saveSection
65731             .append('div')
65732             .attr('class','buttons fillL cf');
65733
65734         var cancelButton = buttonSection
65735             .append('button')
65736             .attr('class', 'secondary-action col5 button cancel-button')
65737             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65738
65739         cancelButton
65740             .append('span')
65741             .attr('class', 'label')
65742             .text(t('commit.cancel'));
65743
65744         var saveButton = buttonSection
65745             .append('button')
65746             .attr('class', 'action col5 button save-button')
65747             .attr('disabled', function() {
65748                 var n = select('.commit-form textarea').node();
65749                 return (n && n.value.length) ? null : true;
65750             })
65751             .on('click.save', function() {
65752                 dispatch$$1.call('save', this, {
65753                     comment: commentField.node().value
65754                 });
65755             });
65756
65757         saveButton
65758             .append('span')
65759             .attr('class', 'label')
65760             .text(t('commit.save'));
65761
65762
65763         // Changes
65764         var changeSection = body
65765             .append('div')
65766             .attr('class', 'commit-section modal-section fillL2');
65767
65768         changeSection.append('h3')
65769             .text(t('commit.changes', { count: summary.length }));
65770
65771         var li = changeSection
65772             .append('ul')
65773             .attr('class', 'changeset-list')
65774             .selectAll('li')
65775             .data(summary);
65776
65777         li = li.enter()
65778             .append('li')
65779             .on('mouseover', mouseover)
65780             .on('mouseout', mouseout)
65781             .on('click', zoomToEntity)
65782             .merge(li);
65783
65784         li.each(function(d) {
65785             select(this)
65786                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
65787         });
65788
65789         li.append('span')
65790             .attr('class', 'change-type')
65791             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
65792
65793         li.append('strong')
65794             .attr('class', 'entity-type')
65795             .text(function(d) {
65796                 var matched = context.presets().match(d.entity, d.graph);
65797                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
65798             });
65799
65800         li.append('span')
65801             .attr('class', 'entity-name')
65802             .text(function(d) {
65803                 var name = utilDisplayName(d.entity) || '',
65804                     string = '';
65805                 if (name !== '') string += ':';
65806                 return string += ' ' + name;
65807             });
65808
65809         li.style('opacity', 0)
65810             .transition()
65811             .style('opacity', 1);
65812
65813
65814         // Call checkComment off the bat, in case a changeset
65815         // comment is recovered from localStorage
65816         utilTriggerEvent(commentField, 'input');
65817
65818
65819         function mouseover(d) {
65820             if (d.entity) {
65821                 context.surface().selectAll(
65822                     utilEntityOrMemberSelector([d.entity.id], context.graph())
65823                 ).classed('hover', true);
65824             }
65825         }
65826
65827
65828         function mouseout() {
65829             context.surface().selectAll('.hover')
65830                 .classed('hover', false);
65831         }
65832
65833
65834         function warningClick(d) {
65835             if (d.entity) {
65836                 context.map().zoomTo(d.entity);
65837                 context.enter(
65838                     modeSelect(context, [d.entity.id]).suppressMenu(true)
65839                 );
65840             }
65841         }
65842
65843
65844         function zoomToEntity(change) {
65845             var entity = change.entity;
65846             if (change.changeType !== 'deleted' &&
65847                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
65848                 context.map().zoomTo(entity);
65849                 context.surface().selectAll(
65850                     utilEntityOrMemberSelector([entity.id], context.graph()))
65851                     .classed('hover', true);
65852             }
65853         }
65854
65855
65856         function checkComment() {
65857             selectAll('.save-section .save-button')
65858                 .attr('disabled', (this.value.length ? null : true));
65859
65860             var googleWarning = clippyArea
65861                .html('')
65862                .selectAll('a')
65863                .data(this.value.match(/google/i) ? [true] : []);
65864
65865             googleWarning.exit()
65866                 .remove();
65867
65868             googleWarning.enter()
65869                .append('a')
65870                .attr('target', '_blank')
65871                .attr('tabindex', -1)
65872                .call(svgIcon('#icon-alert', 'inline'))
65873                .attr('href', t('commit.google_warning_link'))
65874                .append('span')
65875                .text(t('commit.google_warning'));
65876         }
65877     }
65878
65879     return utilRebind(commit, dispatch$$1, 'on');
65880 }
65881
65882 function uiConfirm(selection) {
65883     var modalSelection = uiModal(selection);
65884
65885     modalSelection.select('.modal')
65886         .classed('modal-alert', true);
65887
65888     var section = modalSelection.select('.content');
65889
65890     section.append('div')
65891         .attr('class', 'modal-section header');
65892
65893     section.append('div')
65894         .attr('class', 'modal-section message-text');
65895
65896     var buttons = section.append('div')
65897         .attr('class', 'modal-section buttons cf');
65898
65899
65900     modalSelection.okButton = function() {
65901         buttons
65902             .append('button')
65903             .attr('class', 'action col4')
65904             .on('click.confirm', function() {
65905                 modalSelection.remove();
65906             })
65907             .text(t('confirm.okay'));
65908
65909         return modalSelection;
65910     };
65911
65912
65913     return modalSelection;
65914 }
65915
65916 function uiConflicts(context) {
65917     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
65918         list;
65919
65920
65921     function conflicts(selection$$1) {
65922         var header = selection$$1
65923             .append('div')
65924             .attr('class', 'header fillL');
65925
65926         header
65927             .append('button')
65928             .attr('class', 'fr')
65929             .on('click', function() { dispatch$$1.call('cancel'); })
65930             .call(svgIcon('#icon-close'));
65931
65932         header
65933             .append('h3')
65934             .text(t('save.conflict.header'));
65935
65936         var body = selection$$1
65937             .append('div')
65938             .attr('class', 'body fillL');
65939
65940         body
65941             .append('div')
65942             .attr('class', 'conflicts-help')
65943             .text(t('save.conflict.help'))
65944             .append('a')
65945             .attr('class', 'conflicts-download')
65946             .text(t('save.conflict.download_changes'))
65947             .on('click.download', function() { dispatch$$1.call('download'); });
65948
65949         body
65950             .append('div')
65951             .attr('class', 'conflict-container fillL3')
65952             .call(showConflict, 0);
65953
65954         body
65955             .append('div')
65956             .attr('class', 'conflicts-done')
65957             .attr('opacity', 0)
65958             .style('display', 'none')
65959             .text(t('save.conflict.done'));
65960
65961         var buttons = body
65962             .append('div')
65963             .attr('class','buttons col12 joined conflicts-buttons');
65964
65965         buttons
65966             .append('button')
65967             .attr('disabled', list.length > 1)
65968             .attr('class', 'action conflicts-button col6')
65969             .text(t('save.title'))
65970             .on('click.try_again', function() { dispatch$$1.call('save'); });
65971
65972         buttons
65973             .append('button')
65974             .attr('class', 'secondary-action conflicts-button col6')
65975             .text(t('confirm.cancel'))
65976             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65977     }
65978
65979
65980     function showConflict(selection$$1, index) {
65981         if (index < 0 || index >= list.length) return;
65982
65983         var parent = select(selection$$1.node().parentNode);
65984
65985         // enable save button if this is the last conflict being reviewed..
65986         if (index === list.length - 1) {
65987             window.setTimeout(function() {
65988                 parent.select('.conflicts-button')
65989                     .attr('disabled', null);
65990
65991                 parent.select('.conflicts-done')
65992                     .transition()
65993                     .attr('opacity', 1)
65994                     .style('display', 'block');
65995             }, 250);
65996         }
65997
65998         var item = selection$$1
65999             .selectAll('.conflict')
66000             .data([list[index]]);
66001
66002         var enter = item.enter()
66003             .append('div')
66004             .attr('class', 'conflict');
66005
66006         enter
66007             .append('h4')
66008             .attr('class', 'conflict-count')
66009             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
66010
66011         enter
66012             .append('a')
66013             .attr('class', 'conflict-description')
66014             .attr('href', '#')
66015             .text(function(d) { return d.name; })
66016             .on('click', function(d) {
66017                 zoomToEntity(d.id);
66018                 event.preventDefault();
66019             });
66020
66021         var details = enter
66022             .append('div')
66023             .attr('class', 'conflict-detail-container');
66024
66025         details
66026             .append('ul')
66027             .attr('class', 'conflict-detail-list')
66028             .selectAll('li')
66029             .data(function(d) { return d.details || []; })
66030             .enter()
66031             .append('li')
66032             .attr('class', 'conflict-detail-item')
66033             .html(function(d) { return d; });
66034
66035         details
66036             .append('div')
66037             .attr('class', 'conflict-choices')
66038             .call(addChoices);
66039
66040         details
66041             .append('div')
66042             .attr('class', 'conflict-nav-buttons joined cf')
66043             .selectAll('button')
66044             .data(['previous', 'next'])
66045             .enter()
66046             .append('button')
66047             .text(function(d) { return t('save.conflict.' + d); })
66048             .attr('class', 'conflict-nav-button action col6')
66049             .attr('disabled', function(d, i) {
66050                 return (i === 0 && index === 0) ||
66051                     (i === 1 && index === list.length - 1) || null;
66052             })
66053             .on('click', function(d, i) {
66054                 var container = parent.select('.conflict-container'),
66055                 sign = (i === 0 ? -1 : 1);
66056
66057                 container
66058                     .selectAll('.conflict')
66059                     .remove();
66060
66061                 container
66062                     .call(showConflict, index + sign);
66063
66064                 event.preventDefault();
66065             });
66066
66067         item.exit()
66068             .remove();
66069     }
66070
66071
66072     function addChoices(selection$$1) {
66073         var choices = selection$$1
66074             .append('ul')
66075             .attr('class', 'layer-list')
66076             .selectAll('li')
66077             .data(function(d) { return d.choices || []; });
66078
66079         var enter = choices.enter()
66080             .append('li')
66081             .attr('class', 'layer');
66082
66083         var label = enter
66084             .append('label');
66085
66086         label
66087             .append('input')
66088             .attr('type', 'radio')
66089             .attr('name', function(d) { return d.id; })
66090             .on('change', function(d, i) {
66091                 var ul = this.parentNode.parentNode.parentNode;
66092                 ul.__data__.chosen = i;
66093                 choose(ul, d);
66094             });
66095
66096         label
66097             .append('span')
66098             .text(function(d) { return d.text; });
66099
66100         choices
66101             .each(function(d, i) {
66102                 var ul = this.parentNode;
66103                 if (ul.__data__.chosen === i) choose(ul, d);
66104             });
66105     }
66106
66107
66108     function choose(ul, datum) {
66109         if (event) event.preventDefault();
66110
66111         select(ul)
66112             .selectAll('li')
66113             .classed('active', function(d) { return d === datum; })
66114             .selectAll('input')
66115             .property('checked', function(d) { return d === datum; });
66116
66117         var extent$$1 = geoExtent$$1(),
66118             entity;
66119
66120         entity = context.graph().hasEntity(datum.id);
66121         if (entity) extent$$1._extend(entity.extent(context.graph()));
66122
66123         datum.action();
66124
66125         entity = context.graph().hasEntity(datum.id);
66126         if (entity) extent$$1._extend(entity.extent(context.graph()));
66127
66128         zoomToEntity(datum.id, extent$$1);
66129     }
66130
66131
66132     function zoomToEntity(id, extent$$1) {
66133         context.surface().selectAll('.hover')
66134             .classed('hover', false);
66135
66136         var entity = context.graph().hasEntity(id);
66137         if (entity) {
66138             if (extent$$1) {
66139                 context.map().trimmedExtent(extent$$1);
66140             } else {
66141                 context.map().zoomTo(entity);
66142             }
66143             context.surface().selectAll(
66144                 utilEntityOrMemberSelector([entity.id], context.graph()))
66145                 .classed('hover', true);
66146         }
66147     }
66148
66149
66150     // The conflict list should be an array of objects like:
66151     // {
66152     //     id: id,
66153     //     name: entityName(local),
66154     //     details: merge.conflicts(),
66155     //     chosen: 1,
66156     //     choices: [
66157     //         choice(id, keepMine, forceLocal),
66158     //         choice(id, keepTheirs, forceRemote)
66159     //     ]
66160     // }
66161     conflicts.list = function(_) {
66162         if (!arguments.length) return list;
66163         list = _;
66164         return conflicts;
66165     };
66166
66167
66168     return utilRebind(conflicts, dispatch$$1, 'on');
66169 }
66170
66171 function uiFlash(selection) {
66172     var modalSelection = uiModal(selection);
66173
66174     modalSelection.select('.modal')
66175         .classed('modal-flash', true);
66176
66177     modalSelection.select('.content')
66178         .classed('modal-section', true)
66179         .append('div')
66180         .attr('class', 'description');
66181
66182     modalSelection.on('click.flash', function() {
66183         modalSelection.remove();
66184     });
66185
66186     setTimeout(function() {
66187         modalSelection.remove();
66188         return true;
66189     }, 1500);
66190
66191
66192     return modalSelection;
66193 }
66194
66195 function uiLasso(context) {
66196     var group, polygon;
66197
66198     lasso.coordinates = [];
66199
66200     function lasso(selection$$1) {
66201         context.container()
66202             .classed('lasso', true);
66203
66204         group = selection$$1
66205             .append('g')
66206             .attr('class', 'lasso hide');
66207
66208         polygon = group
66209             .append('path')
66210             .attr('class', 'lasso-path');
66211
66212         group
66213             .call(uiToggle(true));
66214     }
66215
66216
66217     function draw() {
66218         if (polygon) {
66219             polygon.data([lasso.coordinates])
66220                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
66221         }
66222     }
66223
66224
66225     lasso.extent = function () {
66226         return lasso.coordinates.reduce(function(extent$$1, point) {
66227             return extent$$1.extend(geoExtent$$1(point));
66228         }, geoExtent$$1());
66229     };
66230
66231
66232     lasso.p = function(_) {
66233         if (!arguments.length) return lasso;
66234         lasso.coordinates.push(_);
66235         draw();
66236         return lasso;
66237     };
66238
66239
66240     lasso.close = function() {
66241         if (group) {
66242             group.call(uiToggle(false, function() {
66243                 select(this).remove();
66244             }));
66245         }
66246         context.container().classed('lasso', false);
66247     };
66248
66249
66250     return lasso;
66251 }
66252
66253 function uiRadialMenu(context, operations) {
66254     var menu,
66255         center = [0, 0],
66256         tooltip;
66257
66258
66259     var radialMenu = function(selection$$1) {
66260         if (!operations.length) return;
66261
66262         selection$$1.node().parentNode.focus();
66263
66264         function click(operation) {
66265             event.stopPropagation();
66266             if (operation.disabled()) return;
66267             operation();
66268             radialMenu.close();
66269         }
66270
66271         menu = selection$$1
66272             .append('g')
66273             .attr('class', 'radial-menu')
66274             .attr('transform', 'translate(' + center + ')')
66275             .attr('opacity', 0);
66276
66277         menu
66278             .transition()
66279             .attr('opacity', 1);
66280
66281         var r = 50,
66282             a = Math.PI / 4,
66283             a0 = -Math.PI / 4,
66284             a1 = a0 + (operations.length - 1) * a;
66285
66286         menu
66287             .append('path')
66288             .attr('class', 'radial-menu-background')
66289             .attr('d', 'M' + r * Math.sin(a0) + ',' +
66290                              r * Math.cos(a0) +
66291                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
66292                              (r * Math.sin(a1) + 1e-3) + ',' +
66293                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
66294             .attr('stroke-width', 50)
66295             .attr('stroke-linecap', 'round');
66296
66297         var button = menu.selectAll()
66298             .data(operations)
66299             .enter()
66300             .append('g')
66301             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
66302             .classed('disabled', function(d) { return d.disabled(); })
66303             .attr('transform', function(d, i) {
66304                 return 'translate(' + geoRoundCoords([
66305                         r * Math.sin(a0 + i * a),
66306                         r * Math.cos(a0 + i * a)]).join(',') + ')';
66307             });
66308
66309         button
66310             .append('circle')
66311             .attr('r', 15)
66312             .on('click', click)
66313             .on('mousedown', mousedown)
66314             .on('mouseover', mouseover)
66315             .on('mouseout', mouseout);
66316
66317         button
66318             .append('use')
66319             .attr('transform', 'translate(-10,-10)')
66320             .attr('width', '20')
66321             .attr('height', '20')
66322             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
66323
66324         tooltip = select(document.body)
66325             .append('div')
66326             .attr('class', 'tooltip-inner radial-menu-tooltip');
66327
66328         function mousedown() {
66329             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
66330         }
66331
66332         function mouseover(d, i) {
66333             var rect = context.surfaceRect(),
66334                 angle = a0 + i * a,
66335                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
66336                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
66337                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
66338                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
66339
66340             tooltip
66341                 .style('top', null)
66342                 .style('left', null)
66343                 .style('bottom', null)
66344                 .style('right', null)
66345                 .style('display', 'block')
66346                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
66347
66348             if (i === 0) {
66349                 tooltip
66350                     .style('right', right)
66351                     .style('top', top);
66352             } else if (i >= 4) {
66353                 tooltip
66354                     .style('left', left)
66355                     .style('bottom', bottom);
66356             } else {
66357                 tooltip
66358                     .style('left', left)
66359                     .style('top', top);
66360             }
66361         }
66362
66363         function mouseout() {
66364             tooltip.style('display', 'none');
66365         }
66366     };
66367
66368
66369     radialMenu.close = function() {
66370         if (menu) {
66371             menu
66372                 .style('pointer-events', 'none')
66373                 .transition()
66374                 .attr('opacity', 0)
66375                 .remove();
66376         }
66377
66378         if (tooltip) {
66379             tooltip.remove();
66380         }
66381     };
66382
66383
66384     radialMenu.center = function(_) {
66385         if (!arguments.length) return center;
66386         center = _;
66387         return radialMenu;
66388     };
66389
66390
66391     return radialMenu;
66392 }
66393
66394 function uiSelectionList(context, selectedIDs) {
66395
66396     function selectEntity(entity) {
66397         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
66398     }
66399
66400
66401     function deselectEntity(entity) {
66402         event.stopPropagation();
66403         var index = selectedIDs.indexOf(entity.id);
66404         if (index > -1) {
66405             selectedIDs.splice(index, 1);
66406         }
66407         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
66408     }
66409
66410
66411     function selectionList(selection$$1) {
66412         selection$$1.classed('selection-list-pane', true);
66413
66414         var header = selection$$1
66415             .append('div')
66416             .attr('class', 'header fillL cf');
66417
66418         header
66419             .append('h3')
66420             .text(t('inspector.multiselect'));
66421
66422         var listWrap = selection$$1
66423             .append('div')
66424             .attr('class', 'inspector-body');
66425
66426         var list = listWrap
66427             .append('div')
66428             .attr('class', 'feature-list cf');
66429
66430         context.history().on('change.selection-list', drawList);
66431         drawList();
66432
66433
66434         function drawList() {
66435             var entities = selectedIDs
66436                 .map(function(id) { return context.hasEntity(id); })
66437                 .filter(function(entity) { return entity; });
66438
66439             var items = list.selectAll('.feature-list-item')
66440                 .data(entities, osmEntity$$1.key);
66441
66442             items.exit()
66443                 .remove();
66444
66445             // Enter
66446             var enter = items.enter()
66447                 .append('div')
66448                 .attr('class', 'feature-list-item')
66449                 .on('click', selectEntity);
66450
66451             var label = enter
66452                 .append('button')
66453                 .attr('class', 'label');
66454
66455             enter
66456                 .append('button')
66457                 .attr('class', 'close')
66458                 .on('click', deselectEntity)
66459                 .call(svgIcon('#icon-close'));
66460
66461             label
66462                 .append('span')
66463                 .attr('class', 'entity-geom-icon')
66464                 .call(svgIcon('', 'pre-text'));
66465
66466             label
66467                 .append('span')
66468                 .attr('class', 'entity-type');
66469
66470             label
66471                 .append('span')
66472                 .attr('class', 'entity-name');
66473
66474             // Update
66475             items = items.merge(enter);
66476
66477             items.selectAll('.entity-geom-icon use')
66478                 .attr('href', function() {
66479                     var entity = this.parentNode.parentNode.__data__;
66480                     return '#icon-' + context.geometry(entity.id);
66481                 });
66482
66483             items.selectAll('.entity-type')
66484                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
66485
66486             items.selectAll('.entity-name')
66487                 .text(function(entity) { return utilDisplayName(entity); });
66488         }
66489     }
66490
66491     return selectionList;
66492 }
66493
66494 function uiSourceSwitch(context) {
66495     var keys$$1;
66496
66497
66498     function click() {
66499         event.preventDefault();
66500
66501         if (context.history().hasChanges() &&
66502             !window.confirm(t('source_switch.lose_changes'))) return;
66503
66504         var live = select(this)
66505             .classed('live');
66506
66507         context.connection()
66508             .switch(live ? keys$$1[1] : keys$$1[0]);
66509
66510         context.enter(modeBrowse(context));
66511         context.flush();
66512
66513         select(this)
66514             .text(live ? t('source_switch.dev') : t('source_switch.live'))
66515             .classed('live', !live);
66516     }
66517
66518     var sourceSwitch = function(selection$$1) {
66519         selection$$1
66520             .append('a')
66521             .attr('href', '#')
66522             .text(t('source_switch.live'))
66523             .classed('live', true)
66524             .attr('tabindex', -1)
66525             .on('click', click);
66526     };
66527
66528
66529     sourceSwitch.keys = function(_) {
66530         if (!arguments.length) return keys$$1;
66531         keys$$1 = _;
66532         return sourceSwitch;
66533     };
66534
66535
66536     return sourceSwitch;
66537 }
66538
66539 function uiSuccess(context) {
66540     var dispatch$$1 = dispatch('cancel'),
66541         changeset;
66542
66543
66544     function success(selection$$1) {
66545         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
66546             ' ' + context.connection().changesetURL(changeset.id);
66547
66548         var header = selection$$1
66549             .append('div')
66550             .attr('class', 'header fillL');
66551
66552         header
66553             .append('button')
66554             .attr('class', 'fr')
66555             .on('click', function() { dispatch$$1.call('cancel'); })
66556             .call(svgIcon('#icon-close'));
66557
66558         header
66559             .append('h3')
66560             .text(t('success.just_edited'));
66561
66562         var body = selection$$1
66563             .append('div')
66564             .attr('class', 'body save-success fillL');
66565
66566         body
66567             .append('p')
66568             .html(t('success.help_html'));
66569
66570         body
66571             .append('a')
66572             .attr('class', 'details')
66573             .attr('target', '_blank')
66574             .attr('tabindex', -1)
66575             .call(svgIcon('#icon-out-link', 'inline'))
66576             .attr('href', t('success.help_link_url'))
66577             .append('span')
66578             .text(t('success.help_link_text'));
66579
66580         var changesetURL = context.connection().changesetURL(changeset.id);
66581
66582         body
66583             .append('a')
66584             .attr('class', 'button col12 osm')
66585             .attr('target', '_blank')
66586             .attr('href', changesetURL)
66587             .text(t('success.view_on_osm'));
66588
66589         var sharing = {
66590             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
66591             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
66592             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
66593         };
66594
66595         body.selectAll('.button.social')
66596             .data(entries(sharing))
66597             .enter()
66598             .append('a')
66599             .attr('class', 'button social col4')
66600             .attr('target', '_blank')
66601             .attr('href', function(d) { return d.value; })
66602             .call(tooltip()
66603                 .title(function(d) { return t('success.' + d.key); })
66604                 .placement('bottom'))
66605             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
66606     }
66607
66608
66609     success.changeset = function(_) {
66610         if (!arguments.length) return changeset;
66611         changeset = _;
66612         return success;
66613     };
66614
66615
66616     return utilRebind(success, dispatch$$1, 'on');
66617 }
66618
66619 function coreHistory(context) {
66620     var imageryUsed = ['Bing'],
66621         dispatch$$1 = dispatch('change', 'undone', 'redone'),
66622         lock = utilSessionMutex('lock'),
66623         duration = 150,
66624         stack$$1, index, tree$$1;
66625
66626
66627     // internal _act, accepts list of actions and eased time
66628     function _act(actions, t) {
66629         actions = Array.prototype.slice.call(actions);
66630
66631         var annotation;
66632
66633         if (!lodash.isFunction(lodash.last(actions))) {
66634             annotation = actions.pop();
66635         }
66636
66637         stack$$1[index].transform = context.projection.transform();
66638         stack$$1[index].selectedIDs = context.selectedIDs();
66639
66640         var graph = stack$$1[index].graph;
66641         for (var i = 0; i < actions.length; i++) {
66642             graph = actions[i](graph, t);
66643         }
66644
66645         return {
66646             graph: graph,
66647             annotation: annotation,
66648             imageryUsed: imageryUsed
66649         };
66650     }
66651
66652
66653     // internal _perform with eased time
66654     function _perform(args, t) {
66655         var previous = stack$$1[index].graph;
66656         stack$$1 = stack$$1.slice(0, index + 1);
66657         stack$$1.push(_act(args, t));
66658         index++;
66659         return change(previous);
66660     }
66661
66662
66663     // internal _replace with eased time
66664     function _replace(args, t) {
66665         var previous = stack$$1[index].graph;
66666         // assert(index == stack.length - 1)
66667         stack$$1[index] = _act(args, t);
66668         return change(previous);
66669     }
66670
66671
66672     // internal _overwrite with eased time
66673     function _overwrite(args, t) {
66674         var previous = stack$$1[index].graph;
66675         if (index > 0) {
66676             index--;
66677             stack$$1.pop();
66678         }
66679         stack$$1 = stack$$1.slice(0, index + 1);
66680         stack$$1.push(_act(args, t));
66681         index++;
66682         return change(previous);
66683     }
66684
66685
66686     // determine diffrence and dispatch a change event
66687     function change(previous) {
66688         var difference = coreDifference(previous, history.graph());
66689         dispatch$$1.call('change', this, difference);
66690         return difference;
66691     }
66692
66693
66694     // iD uses namespaced keys so multiple installations do not conflict
66695     function getKey(n) {
66696         return 'iD_' + window.location.origin + '_' + n;
66697     }
66698
66699
66700     var history = {
66701
66702         graph: function() {
66703             return stack$$1[index].graph;
66704         },
66705
66706
66707         base: function() {
66708             return stack$$1[0].graph;
66709         },
66710
66711
66712         merge: function(entities, extent$$1) {
66713             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
66714             tree$$1.rebase(entities, false);
66715
66716             dispatch$$1.call('change', this, undefined, extent$$1);
66717         },
66718
66719
66720         perform: function() {
66721             // complete any transition already in progress
66722             select(document).interrupt('history.perform');
66723
66724             var transitionable = false,
66725                 action0 = arguments[0];
66726
66727             if (arguments.length === 1 ||
66728                 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
66729                 transitionable = !!action0.transitionable;
66730             }
66731
66732             if (transitionable) {
66733                 var origArguments = arguments;
66734                 select(document)
66735                     .transition('history.perform')
66736                     .duration(duration)
66737                     .ease(linear$1)
66738                     .tween('history.tween', function() {
66739                         return function(t) {
66740                             if (t < 1) _overwrite([action0], t);
66741                         };
66742                     })
66743                     .on('start', function() {
66744                         _perform([action0], 0);
66745                     })
66746                     .on('end interrupt', function() {
66747                         _overwrite(origArguments, 1);
66748                     });
66749
66750             } else {
66751                 return _perform(arguments);
66752             }
66753         },
66754
66755
66756         replace: function() {
66757             select(document).interrupt('history.perform');
66758             return _replace(arguments, 1);
66759         },
66760
66761
66762         // Same as calling pop and then perform
66763         overwrite: function() {
66764             select(document).interrupt('history.perform');
66765             return _overwrite(arguments, 1);
66766         },
66767
66768
66769         pop: function() {
66770             select(document).interrupt('history.perform');
66771
66772             var previous = stack$$1[index].graph;
66773             if (index > 0) {
66774                 index--;
66775                 stack$$1.pop();
66776                 return change(previous);
66777             }
66778         },
66779
66780
66781         undo: function() {
66782             select(document).interrupt('history.perform');
66783
66784             var previous = stack$$1[index].graph;
66785
66786             // Pop to the next annotated state.
66787             while (index > 0) {
66788                 index--;
66789                 if (stack$$1[index].annotation) break;
66790             }
66791
66792             dispatch$$1.call('undone', this, stack$$1[index]);
66793             return change(previous);
66794         },
66795
66796
66797         redo: function() {
66798             select(document).interrupt('history.perform');
66799
66800             var previous = stack$$1[index].graph;
66801             while (index < stack$$1.length - 1) {
66802                 index++;
66803                 if (stack$$1[index].annotation) break;
66804             }
66805
66806             dispatch$$1.call('redone', this, stack$$1[index]);
66807             return change(previous);
66808         },
66809
66810
66811         undoAnnotation: function() {
66812             var i = index;
66813             while (i >= 0) {
66814                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66815                 i--;
66816             }
66817         },
66818
66819
66820         redoAnnotation: function() {
66821             var i = index + 1;
66822             while (i <= stack$$1.length - 1) {
66823                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66824                 i++;
66825             }
66826         },
66827
66828
66829         intersects: function(extent$$1) {
66830             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
66831         },
66832
66833
66834         difference: function() {
66835             var base = stack$$1[0].graph,
66836                 head = stack$$1[index].graph;
66837             return coreDifference(base, head);
66838         },
66839
66840
66841         changes: function(action) {
66842             var base = stack$$1[0].graph,
66843                 head = stack$$1[index].graph;
66844
66845             if (action) {
66846                 head = action(head);
66847             }
66848
66849             var difference = coreDifference(base, head);
66850
66851             return {
66852                 modified: difference.modified(),
66853                 created: difference.created(),
66854                 deleted: difference.deleted()
66855             };
66856         },
66857
66858
66859         validate: function(changes) {
66860             return lodash(Validations)
66861                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
66862                 .flatten()
66863                 .value();
66864         },
66865
66866
66867         hasChanges: function() {
66868             return this.difference().length() > 0;
66869         },
66870
66871
66872         imageryUsed: function(sources) {
66873             if (sources) {
66874                 imageryUsed = sources;
66875                 return history;
66876             } else {
66877                 return lodash(stack$$1.slice(1, index + 1))
66878                     .map('imageryUsed')
66879                     .flatten()
66880                     .uniq()
66881                     .without(undefined, 'Custom')
66882                     .value();
66883             }
66884         },
66885
66886
66887         reset: function() {
66888             stack$$1 = [{graph: coreGraph$$1()}];
66889             index = 0;
66890             tree$$1 = coreTree(stack$$1[0].graph);
66891             dispatch$$1.call('change');
66892             return history;
66893         },
66894
66895
66896         toJSON: function() {
66897             if (!this.hasChanges()) return;
66898
66899             var allEntities = {},
66900                 baseEntities = {},
66901                 base = stack$$1[0];
66902
66903             var s = stack$$1.map(function(i) {
66904                 var modified = [], deleted = [];
66905
66906                 lodash.forEach(i.graph.entities, function(entity, id) {
66907                     if (entity) {
66908                         var key = osmEntity$$1.key(entity);
66909                         allEntities[key] = entity;
66910                         modified.push(key);
66911                     } else {
66912                         deleted.push(id);
66913                     }
66914
66915                     // make sure that the originals of changed or deleted entities get merged
66916                     // into the base of the stack after restoring the data from JSON.
66917                     if (id in base.graph.entities) {
66918                         baseEntities[id] = base.graph.entities[id];
66919                     }
66920                     // get originals of parent entities too
66921                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
66922                         if (parentId in base.graph.entities) {
66923                             baseEntities[parentId] = base.graph.entities[parentId];
66924                         }
66925                     });
66926                 });
66927
66928                 var x = {};
66929
66930                 if (modified.length) x.modified = modified;
66931                 if (deleted.length) x.deleted = deleted;
66932                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
66933                 if (i.annotation) x.annotation = i.annotation;
66934
66935                 return x;
66936             });
66937
66938             return JSON.stringify({
66939                 version: 3,
66940                 entities: lodash.values(allEntities),
66941                 baseEntities: lodash.values(baseEntities),
66942                 stack: s,
66943                 nextIDs: osmEntity$$1.id.next,
66944                 index: index
66945             });
66946         },
66947
66948
66949         fromJSON: function(json$$1, loadChildNodes) {
66950             var h = JSON.parse(json$$1),
66951                 loadComplete = true;
66952
66953             osmEntity$$1.id.next = h.nextIDs;
66954             index = h.index;
66955
66956             if (h.version === 2 || h.version === 3) {
66957                 var allEntities = {};
66958
66959                 h.entities.forEach(function(entity) {
66960                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
66961                 });
66962
66963                 if (h.version === 3) {
66964                     // This merges originals for changed entities into the base of
66965                     // the stack even if the current stack doesn't have them (for
66966                     // example when iD has been restarted in a different region)
66967                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
66968                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
66969                     tree$$1.rebase(baseEntities, true);
66970
66971                     // When we restore a modified way, we also need to fetch any missing
66972                     // childnodes that would normally have been downloaded with it.. #2142
66973                     if (loadChildNodes) {
66974                         var missing =  lodash(baseEntities)
66975                                 .filter({ type: 'way' })
66976                                 .map('nodes')
66977                                 .flatten()
66978                                 .uniq()
66979                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
66980                                 .value();
66981
66982                         if (!lodash.isEmpty(missing)) {
66983                             loadComplete = false;
66984                             context.redrawEnable(false);
66985
66986                             var loading = uiLoading(context).blocking(true);
66987                             context.container().call(loading);
66988
66989                             var childNodesLoaded = function(err, result) {
66990                                 if (!err) {
66991                                     var visible = lodash.groupBy(result.data, 'visible');
66992                                     if (!lodash.isEmpty(visible.true)) {
66993                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
66994                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
66995                                         tree$$1.rebase(visible.true, true);
66996                                     }
66997
66998                                     // fetch older versions of nodes that were deleted..
66999                                     lodash.each(visible.false, function(entity) {
67000                                         context.connection()
67001                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
67002                                     });
67003                                 }
67004
67005                                 if (err || lodash.isEmpty(missing)) {
67006                                     loading.close();
67007                                     context.redrawEnable(true);
67008                                     dispatch$$1.call('change');
67009                                 }
67010                             };
67011
67012                             context.connection().loadMultiple(missing, childNodesLoaded);
67013                         }
67014                     }
67015                 }
67016
67017                 stack$$1 = h.stack.map(function(d) {
67018                     var entities = {}, entity;
67019
67020                     if (d.modified) {
67021                         d.modified.forEach(function(key) {
67022                             entity = allEntities[key];
67023                             entities[entity.id] = entity;
67024                         });
67025                     }
67026
67027                     if (d.deleted) {
67028                         d.deleted.forEach(function(id) {
67029                             entities[id] = undefined;
67030                         });
67031                     }
67032
67033                     return {
67034                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
67035                         annotation: d.annotation,
67036                         imageryUsed: d.imageryUsed
67037                     };
67038                 });
67039
67040             } else { // original version
67041                 stack$$1 = h.stack.map(function(d) {
67042                     var entities = {};
67043
67044                     for (var i in d.entities) {
67045                         var entity = d.entities[i];
67046                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
67047                     }
67048
67049                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
67050                     return d;
67051                 });
67052             }
67053
67054             if (loadComplete) {
67055                 dispatch$$1.call('change');
67056             }
67057
67058             return history;
67059         },
67060
67061
67062         save: function() {
67063             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
67064             return history;
67065         },
67066
67067
67068         clearSaved: function() {
67069             context.debouncedSave.cancel();
67070             if (lock.locked()) context.storage(getKey('saved_history'), null);
67071             return history;
67072         },
67073
67074
67075         lock: function() {
67076             return lock.lock();
67077         },
67078
67079
67080         unlock: function() {
67081             lock.unlock();
67082         },
67083
67084
67085         // is iD not open in another window and it detects that
67086         // there's a history stored in localStorage that's recoverable?
67087         restorableChanges: function() {
67088             return lock.locked() && !!context.storage(getKey('saved_history'));
67089         },
67090
67091
67092         // load history from a version stored in localStorage
67093         restore: function() {
67094             if (!lock.locked()) return;
67095
67096             var json$$1 = context.storage(getKey('saved_history'));
67097             if (json$$1) history.fromJSON(json$$1, true);
67098         },
67099
67100
67101         _getKey: getKey
67102
67103     };
67104
67105
67106     history.reset();
67107
67108     return utilRebind(history, dispatch$$1, 'on');
67109 }
67110
67111 function presetCollection(collection) {
67112     var maxSearchResults = 50,
67113         maxSuggestionResults = 10;
67114
67115     var presets = {
67116
67117         collection: collection,
67118
67119
67120         item: function(id) {
67121             return lodash.find(collection, function(d) {
67122                 return d.id === id;
67123             });
67124         },
67125
67126
67127         matchGeometry: function(geometry) {
67128             return presetCollection(collection.filter(function(d) {
67129                 return d.matchGeometry(geometry);
67130             }));
67131         },
67132
67133
67134         search: function(value, geometry) {
67135             if (!value) return this;
67136
67137             function leading(a) {
67138                 var index = a.indexOf(value);
67139                 return index === 0 || a[index - 1] === ' ';
67140             }
67141
67142             function suggestionName(name) {
67143                 var nameArray = name.split(' - ');
67144                 if (nameArray.length > 1) {
67145                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
67146                 }
67147                 return name.toLowerCase();
67148             }
67149
67150
67151             value = value.toLowerCase();
67152
67153             var searchable = lodash.filter(collection, function(a) {
67154                     return a.searchable !== false && a.suggestion !== true;
67155                 }),
67156                 suggestions = lodash.filter(collection, function(a) {
67157                     return a.suggestion === true;
67158                 });
67159
67160
67161             // matches value to preset.name
67162             var leading_name = lodash.filter(searchable, function(a) {
67163                     return leading(a.name().toLowerCase());
67164                 }).sort(function(a, b) {
67165                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
67166                     if (i === 0) return a.name().length - b.name().length;
67167                     else return i;
67168                 });
67169
67170             // matches value to preset.terms values
67171             var leading_terms = lodash.filter(searchable, function(a) {
67172                     return lodash.some(a.terms() || [], leading);
67173                 });
67174
67175             // matches value to preset.tags values
67176             var leading_tag_values = lodash.filter(searchable, function(a) {
67177                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
67178                 });
67179
67180
67181             // finds close matches to value in preset.name
67182             var similar_name = searchable.map(function(a) {
67183                     return {
67184                         preset: a,
67185                         dist: utilEditDistance(value, a.name())
67186                     };
67187                 }).filter(function(a) {
67188                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
67189                 }).sort(function(a, b) {
67190                     return a.dist - b.dist;
67191                 }).map(function(a) {
67192                     return a.preset;
67193                 });
67194
67195             // finds close matches to value in preset.terms
67196             var similar_terms = lodash.filter(searchable, function(a) {
67197                     return lodash.some(a.terms() || [], function(b) {
67198                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
67199                     });
67200                 });
67201
67202             var leading_suggestions = lodash.filter(suggestions, function(a) {
67203                     return leading(suggestionName(a.name()));
67204                 }).sort(function(a, b) {
67205                     a = suggestionName(a.name());
67206                     b = suggestionName(b.name());
67207                     var i = a.indexOf(value) - b.indexOf(value);
67208                     if (i === 0) return a.length - b.length;
67209                     else return i;
67210                 });
67211
67212             var similar_suggestions = suggestions.map(function(a) {
67213                     return {
67214                         preset: a,
67215                         dist: utilEditDistance(value, suggestionName(a.name()))
67216                     };
67217                 }).filter(function(a) {
67218                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
67219                 }).sort(function(a, b) {
67220                     return a.dist - b.dist;
67221                 }).map(function(a) {
67222                     return a.preset;
67223                 });
67224
67225             var other = presets.item(geometry);
67226
67227             var results = leading_name.concat(
67228                     leading_terms,
67229                     leading_tag_values,
67230                     leading_suggestions.slice(0, maxSuggestionResults + 5),
67231                     similar_name,
67232                     similar_terms,
67233                     similar_suggestions.slice(0, maxSuggestionResults)
67234                 ).slice(0, maxSearchResults - 1);
67235
67236             return presetCollection(lodash.uniq(results.concat(other)));
67237         }
67238     };
67239
67240
67241     return presets;
67242 }
67243
67244 function presetCategory(id, category, all) {
67245     category = lodash.clone(category);
67246
67247     category.id = id;
67248
67249
67250     category.members = presetCollection(category.members.map(function(id) {
67251         return all.item(id);
67252     }));
67253
67254
67255     category.matchGeometry = function(geometry) {
67256         return category.geometry.indexOf(geometry) >= 0;
67257     };
67258
67259
67260     category.matchScore = function() {
67261         return -1;
67262     };
67263
67264
67265     category.name = function() {
67266         return t('presets.categories.' + id + '.name', {'default': id});
67267     };
67268
67269
67270     category.terms = function() {
67271         return [];
67272     };
67273
67274
67275     return category;
67276 }
67277
67278 function presetField(id, field) {
67279     field = lodash.clone(field);
67280
67281     field.id = id;
67282
67283
67284     field.matchGeometry = function(geometry) {
67285         return !field.geometry || field.geometry === geometry;
67286     };
67287
67288
67289     field.t = function(scope, options) {
67290         return t('presets.fields.' + id + '.' + scope, options);
67291     };
67292
67293
67294     field.label = function() {
67295         return field.t('label', {'default': id});
67296     };
67297
67298
67299     var placeholder = field.placeholder;
67300     field.placeholder = function() {
67301         return field.t('placeholder', {'default': placeholder});
67302     };
67303
67304
67305     return field;
67306 }
67307
67308 function presetPreset(id, preset, fields) {
67309     preset = lodash.clone(preset);
67310
67311     preset.id = id;
67312     preset.fields = (preset.fields || []).map(getFields);
67313     preset.geometry = (preset.geometry || []);
67314
67315
67316     function getFields(f) {
67317         return fields[f];
67318     }
67319
67320
67321     preset.matchGeometry = function(geometry) {
67322         return preset.geometry.indexOf(geometry) >= 0;
67323     };
67324
67325
67326     var matchScore = preset.matchScore || 1;
67327     preset.matchScore = function(entity) {
67328         var tags = preset.tags,
67329             score = 0;
67330
67331         for (var t$$1 in tags) {
67332             if (entity.tags[t$$1] === tags[t$$1]) {
67333                 score += matchScore;
67334             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
67335                 score += matchScore / 2;
67336             } else {
67337                 return -1;
67338             }
67339         }
67340
67341         return score;
67342     };
67343
67344
67345     preset.t = function(scope, options) {
67346         return t('presets.presets.' + id + '.' + scope, options);
67347     };
67348
67349
67350     var name = preset.name || '';
67351     preset.name = function() {
67352         if (preset.suggestion) {
67353             id = id.split('/');
67354             id = id[0] + '/' + id[1];
67355             return name + ' - ' + t('presets.presets.' + id + '.name');
67356         }
67357         return preset.t('name', {'default': name});
67358     };
67359
67360
67361     preset.terms = function() {
67362         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
67363     };
67364
67365
67366     preset.isFallback = function() {
67367         var tagCount = Object.keys(preset.tags).length;
67368         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
67369     };
67370
67371
67372     preset.reference = function(geometry) {
67373         var key = Object.keys(preset.tags)[0],
67374             value = preset.tags[key];
67375
67376         if (geometry === 'relation' && key === 'type') {
67377             if (value in preset.tags) {
67378                 key = value;
67379                 value = preset.tags[key];
67380             } else {
67381                 return { rtype: value };
67382             }
67383         }
67384
67385         if (value === '*') {
67386             return { key: key };
67387         } else {
67388             return { key: key, value: value };
67389         }
67390     };
67391
67392
67393     var removeTags = preset.removeTags || preset.tags;
67394     preset.removeTags = function(tags, geometry) {
67395         tags = lodash.omit(tags, lodash.keys(removeTags));
67396
67397         for (var f in preset.fields) {
67398             var field = preset.fields[f];
67399             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
67400                 delete tags[field.key];
67401             }
67402         }
67403
67404         delete tags.area;
67405         return tags;
67406     };
67407
67408
67409     var applyTags = preset.addTags || preset.tags;
67410     preset.applyTags = function(tags, geometry) {
67411         var k;
67412
67413         tags = lodash.clone(tags);
67414
67415         for (k in applyTags) {
67416             if (applyTags[k] === '*') {
67417                 tags[k] = 'yes';
67418             } else {
67419                 tags[k] = applyTags[k];
67420             }
67421         }
67422
67423         // Add area=yes if necessary.
67424         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
67425         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
67426         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
67427         if (geometry === 'area') {
67428             var needsAreaTag = true;
67429             if (preset.geometry.indexOf('line') === -1) {
67430                 for (k in applyTags) {
67431                     if (k in areaKeys) {
67432                         needsAreaTag = false;
67433                         break;
67434                     }
67435                 }
67436             }
67437             if (needsAreaTag) {
67438                 tags.area = 'yes';
67439             }
67440         }
67441
67442         for (var f in preset.fields) {
67443             var field = preset.fields[f];
67444             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
67445                 tags[field.key] = field.default;
67446             }
67447         }
67448
67449         return tags;
67450     };
67451
67452
67453     return preset;
67454 }
67455
67456 function presetIndex() {
67457     // a presetCollection with methods for
67458     // loading new data and returning defaults
67459
67460     var all = presetCollection([]),
67461         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
67462         fields = {},
67463         universal = [],
67464         recent = presetCollection([]);
67465
67466     // Index of presets by (geometry, tag key).
67467     var index = {
67468         point: {},
67469         vertex: {},
67470         line: {},
67471         area: {},
67472         relation: {}
67473     };
67474
67475     all.match = function(entity, resolver) {
67476         var geometry = entity.geometry(resolver);
67477
67478         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
67479         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
67480             geometry = 'point';
67481         }
67482
67483         var geometryMatches = index[geometry],
67484             best = -1,
67485             match;
67486
67487         for (var k in entity.tags) {
67488             var keyMatches = geometryMatches[k];
67489             if (!keyMatches) continue;
67490
67491             for (var i = 0; i < keyMatches.length; i++) {
67492                 var score = keyMatches[i].matchScore(entity);
67493                 if (score > best) {
67494                     best = score;
67495                     match = keyMatches[i];
67496                 }
67497             }
67498         }
67499
67500         return match || all.item(geometry);
67501     };
67502
67503
67504     // Because of the open nature of tagging, iD will never have a complete
67505     // list of tags used in OSM, so we want it to have logic like "assume
67506     // that a closed way with an amenity tag is an area, unless the amenity
67507     // is one of these specific types". This function computes a structure
67508     // that allows testing of such conditions, based on the presets designated
67509     // as as supporting (or not supporting) the area geometry.
67510     //
67511     // The returned object L is a whitelist/blacklist of tags. A closed way
67512     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
67513     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
67514     // and the subkeys form the blacklist.
67515     all.areaKeys = function() {
67516         var areaKeys = {},
67517             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
67518             presets = lodash.reject(all.collection, 'suggestion');
67519
67520         // whitelist
67521         presets.forEach(function(d) {
67522             for (var key in d.tags) break;
67523             if (!key) return;
67524             if (ignore.indexOf(key) !== -1) return;
67525
67526             if (d.geometry.indexOf('area') !== -1) {
67527                 areaKeys[key] = areaKeys[key] || {};
67528             }
67529         });
67530
67531         // blacklist
67532         presets.forEach(function(d) {
67533             for (var key in d.tags) break;
67534             if (!key) return;
67535             if (ignore.indexOf(key) !== -1) return;
67536
67537             var value = d.tags[key];
67538             if (d.geometry.indexOf('area') === -1 &&
67539                 d.geometry.indexOf('line') !== -1 &&
67540                 key in areaKeys && value !== '*') {
67541                 areaKeys[key][value] = true;
67542             }
67543         });
67544
67545         return areaKeys;
67546     };
67547
67548
67549     all.init = function() {
67550         var d = data.presets;
67551
67552         if (d.fields) {
67553             lodash.forEach(d.fields, function(d, id) {
67554                 fields[id] = presetField(id, d);
67555                 if (d.universal) universal.push(fields[id]);
67556             });
67557         }
67558
67559         if (d.presets) {
67560             lodash.forEach(d.presets, function(d, id) {
67561                 all.collection.push(presetPreset(id, d, fields));
67562             });
67563         }
67564
67565         if (d.categories) {
67566             lodash.forEach(d.categories, function(d, id) {
67567                 all.collection.push(presetCategory(id, d, all));
67568             });
67569         }
67570
67571         if (d.defaults) {
67572             var getItem = lodash.bind(all.item, all);
67573             defaults = {
67574                 area: presetCollection(d.defaults.area.map(getItem)),
67575                 line: presetCollection(d.defaults.line.map(getItem)),
67576                 point: presetCollection(d.defaults.point.map(getItem)),
67577                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
67578                 relation: presetCollection(d.defaults.relation.map(getItem))
67579             };
67580         }
67581
67582         for (var i = 0; i < all.collection.length; i++) {
67583             var preset = all.collection[i],
67584                 geometry = preset.geometry;
67585
67586             for (var j = 0; j < geometry.length; j++) {
67587                 var g = index[geometry[j]];
67588                 for (var k in preset.tags) {
67589                     (g[k] = g[k] || []).push(preset);
67590                 }
67591             }
67592         }
67593
67594         return all;
67595     };
67596
67597     all.field = function(id) {
67598         return fields[id];
67599     };
67600
67601     all.universal = function() {
67602         return universal;
67603     };
67604
67605     all.defaults = function(geometry, n) {
67606         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
67607             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
67608         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
67609     };
67610
67611     all.choose = function(preset) {
67612         if (!preset.isFallback()) {
67613             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
67614         }
67615         return all;
67616     };
67617
67618     return all;
67619 }
67620
67621 var areaKeys = {};
67622
67623 function setAreaKeys(value) {
67624     areaKeys = value;
67625 }
67626
67627
67628 function coreContext() {
67629
67630     // create a special translation that contains the keys in place of the strings
67631     var tkeys = lodash.cloneDeep(en);
67632     var parents = [];
67633
67634     function traverser(v, k, obj) {
67635         parents.push(k);
67636         if (lodash.isObject(v)) {
67637             lodash.forOwn(v, traverser);
67638         } else if (lodash.isString(v)) {
67639             obj[k] = parents.join('.');
67640         }
67641         parents.pop();
67642     }
67643
67644     lodash.forOwn(tkeys, traverser);
67645     addTranslation('_tkeys_', tkeys);
67646
67647     addTranslation('en', en);
67648     setLocale('en');
67649
67650     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
67651         context = {};
67652
67653     // https://github.com/openstreetmap/iD/issues/772
67654     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
67655     var storage;
67656     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
67657     storage = storage || (function() {
67658         var s = {};
67659         return {
67660             getItem: function(k) { return s[k]; },
67661             setItem: function(k, v) { s[k] = v; },
67662             removeItem: function(k) { delete s[k]; }
67663         };
67664     })();
67665
67666     context.storage = function(k, v) {
67667         try {
67668             if (arguments.length === 1) return storage.getItem(k);
67669             else if (v === null) storage.removeItem(k);
67670             else storage.setItem(k, v);
67671         } catch (e) {
67672             // localstorage quota exceeded
67673             /* eslint-disable no-console */
67674             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
67675             /* eslint-enable no-console */
67676         }
67677     };
67678
67679
67680     /* Straight accessors. Avoid using these if you can. */
67681     var ui, connection, history;
67682     context.ui = function() { return ui; };
67683     context.connection = function() { return connection; };
67684     context.history = function() { return history; };
67685
67686
67687     /* Connection */
67688     function entitiesLoaded(err, result) {
67689         if (!err) history.merge(result.data, result.extent);
67690     }
67691
67692     context.preauth = function(options) {
67693         connection.switch(options);
67694         return context;
67695     };
67696
67697     context.loadTiles = function(projection, dimensions, callback) {
67698         function done(err, result) {
67699             entitiesLoaded(err, result);
67700             if (callback) callback(err, result);
67701         }
67702         connection.loadTiles(projection, dimensions, done);
67703     };
67704
67705     context.loadEntity = function(id, callback) {
67706         function done(err, result) {
67707             entitiesLoaded(err, result);
67708             if (callback) callback(err, result);
67709         }
67710         connection.loadEntity(id, done);
67711     };
67712
67713     context.zoomToEntity = function(id, zoomTo) {
67714         if (zoomTo !== false) {
67715             this.loadEntity(id, function(err, result) {
67716                 if (err) return;
67717                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
67718                 if (entity) { map$$1.zoomTo(entity); }
67719             });
67720         }
67721
67722         map$$1.on('drawn.zoomToEntity', function() {
67723             if (!context.hasEntity(id)) return;
67724             map$$1.on('drawn.zoomToEntity', null);
67725             context.on('enter.zoomToEntity', null);
67726             context.enter(modeSelect(context, [id]));
67727         });
67728
67729         context.on('enter.zoomToEntity', function() {
67730             if (mode.id !== 'browse') {
67731                 map$$1.on('drawn.zoomToEntity', null);
67732                 context.on('enter.zoomToEntity', null);
67733             }
67734         });
67735     };
67736
67737     var minEditableZoom = 16;
67738     context.minEditableZoom = function(_) {
67739         if (!arguments.length) return minEditableZoom;
67740         minEditableZoom = _;
67741         connection.tileZoom(_);
67742         return context;
67743     };
67744
67745
67746     /* History */
67747     var inIntro = false;
67748     context.inIntro = function(_) {
67749         if (!arguments.length) return inIntro;
67750         inIntro = _;
67751         return context;
67752     };
67753
67754     context.save = function() {
67755         // no history save, no message onbeforeunload
67756         if (inIntro || select('.modal').size()) return;
67757
67758         var canSave;
67759         if (mode && mode.id === 'save') {
67760             canSave = false;
67761         } else {
67762             canSave = context.selectedIDs().every(function(id) {
67763                 var entity = context.hasEntity(id);
67764                 return entity && !entity.isDegenerate();
67765             });
67766         }
67767
67768         if (canSave) {
67769             history.save();
67770         }
67771         if (history.hasChanges()) {
67772             return t('save.unsaved_changes');
67773         }
67774     };
67775
67776
67777     /* Graph */
67778     context.hasEntity = function(id) {
67779         return history.graph().hasEntity(id);
67780     };
67781     context.entity = function(id) {
67782         return history.graph().entity(id);
67783     };
67784     context.childNodes = function(way) {
67785         return history.graph().childNodes(way);
67786     };
67787     context.geometry = function(id) {
67788         return context.entity(id).geometry(history.graph());
67789     };
67790
67791
67792     /* Modes */
67793     var mode;
67794     context.mode = function() {
67795         return mode;
67796     };
67797     context.enter = function(newMode) {
67798         if (mode) {
67799             mode.exit();
67800             dispatch$$1.call('exit', this, mode);
67801         }
67802
67803         mode = newMode;
67804         mode.enter();
67805         dispatch$$1.call('enter', this, mode);
67806     };
67807
67808     context.selectedIDs = function() {
67809         if (mode && mode.selectedIDs) {
67810             return mode.selectedIDs();
67811         } else {
67812             return [];
67813         }
67814     };
67815
67816
67817     /* Behaviors */
67818     context.install = function(behavior) {
67819         context.surface().call(behavior);
67820     };
67821     context.uninstall = function(behavior) {
67822         context.surface().call(behavior.off);
67823     };
67824
67825
67826     /* Copy/Paste */
67827     var copyIDs = [], copyGraph;
67828     context.copyGraph = function() { return copyGraph; };
67829     context.copyIDs = function(_) {
67830         if (!arguments.length) return copyIDs;
67831         copyIDs = _;
67832         copyGraph = history.graph();
67833         return context;
67834     };
67835
67836
67837     /* Background */
67838     var background;
67839     context.background = function() { return background; };
67840
67841
67842     /* Features */
67843     var features;
67844     context.features = function() { return features; };
67845     context.hasHiddenConnections = function(id) {
67846         var graph = history.graph(),
67847             entity = graph.entity(id);
67848         return features.hasHiddenConnections(entity, graph);
67849     };
67850
67851
67852     /* Presets */
67853     var presets;
67854     context.presets = function() { return presets; };
67855
67856
67857     /* Map */
67858     var map$$1;
67859     context.map = function() { return map$$1; };
67860     context.layers = function() { return map$$1.layers; };
67861     context.surface = function() { return map$$1.surface; };
67862     context.editable = function() { return map$$1.editable(); };
67863
67864     context.surfaceRect = function() {
67865         // Work around a bug in Firefox.
67866         //   http://stackoverflow.com/questions/18153989/
67867         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
67868         return context.surface().node().parentNode.getBoundingClientRect();
67869     };
67870
67871
67872     /* Debug */
67873     var debugFlags = {
67874         tile: false,
67875         collision: false,
67876         imagery: false,
67877         imperial: false,
67878         driveLeft: false
67879     };
67880     context.debugFlags = function() {
67881         return debugFlags;
67882     };
67883     context.setDebug = function(flag, val) {
67884         if (arguments.length === 1) val = true;
67885         debugFlags[flag] = val;
67886         dispatch$$1.call('change');
67887         return context;
67888     };
67889     context.getDebug = function(flag) {
67890         return flag && debugFlags[flag];
67891     };
67892
67893
67894     /* Container */
67895     var container, embed;
67896     context.container = function(_) {
67897         if (!arguments.length) return container;
67898         container = _;
67899         container.classed('id-container', true);
67900         return context;
67901     };
67902     context.embed = function(_) {
67903         if (!arguments.length) return embed;
67904         embed = _;
67905         return context;
67906     };
67907
67908
67909     /* Assets */
67910     var assetPath = '';
67911     context.assetPath = function(_) {
67912         if (!arguments.length) return assetPath;
67913         assetPath = _;
67914         return context;
67915     };
67916
67917     var assetMap = {};
67918     context.assetMap = function(_) {
67919         if (!arguments.length) return assetMap;
67920         assetMap = _;
67921         return context;
67922     };
67923
67924     context.asset = function(_) {
67925         var filename = assetPath + _;
67926         return assetMap[filename] || filename;
67927     };
67928
67929     context.imagePath = function(_) {
67930         return context.asset('img/' + _);
67931     };
67932
67933
67934     /* locales */
67935     // `locale` variable contains a "requested locale".
67936     // It won't become the `currentLocale` until after loadLocale() is called.
67937     var locale, localePath;
67938
67939     context.locale = function(loc, path$$1) {
67940         if (!arguments.length) return currentLocale;
67941         locale = loc;
67942         localePath = path$$1;
67943         return context;
67944     };
67945
67946     context.loadLocale = function(callback) {
67947         if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
67948             localePath = localePath || context.asset('locales/' + locale + '.json');
67949             json(localePath, function(err, result) {
67950                 if (!err) {
67951                     addTranslation(locale, result[locale]);
67952                     setLocale(locale);
67953                     utilDetect(true);
67954                 }
67955                 if (callback) {
67956                     callback(err);
67957                 }
67958             });
67959         } else {
67960             if (locale) {
67961                 setLocale(locale);
67962                 utilDetect(true);
67963             }
67964             if (callback) {
67965                 callback();
67966             }
67967         }
67968     };
67969
67970
67971     /* reset (aka flush) */
67972     context.reset = context.flush = function() {
67973         context.debouncedSave.cancel();
67974         lodash.each(services, function(service) {
67975             if (service && typeof service.reset === 'function') {
67976                 service.reset(context);
67977             }
67978         });
67979         features.reset();
67980         history.reset();
67981         return context;
67982     };
67983
67984
67985     /* Init */
67986     context.version = '2.1.3';
67987
67988     context.projection = geoRawMercator();
67989
67990     locale = utilDetect().locale;
67991     if (locale && !dataLocales.hasOwnProperty(locale)) {
67992         locale = locale.split('-')[0];
67993     }
67994
67995     history = coreHistory(context);
67996     context.graph = history.graph;
67997     context.changes = history.changes;
67998     context.intersects = history.intersects;
67999
68000     // Debounce save, since it's a synchronous localStorage write,
68001     // and history changes can happen frequently (e.g. when dragging).
68002     context.debouncedSave = lodash.debounce(context.save, 350);
68003     function withDebouncedSave(fn) {
68004         return function() {
68005             var result = fn.apply(history, arguments);
68006             context.debouncedSave();
68007             return result;
68008         };
68009     }
68010
68011     context.perform = withDebouncedSave(history.perform);
68012     context.replace = withDebouncedSave(history.replace);
68013     context.pop = withDebouncedSave(history.pop);
68014     context.overwrite = withDebouncedSave(history.overwrite);
68015     context.undo = withDebouncedSave(history.undo);
68016     context.redo = withDebouncedSave(history.redo);
68017
68018     ui = uiInit(context);
68019
68020     connection = services.osm;
68021     background = rendererBackground(context);
68022     features = rendererFeatures(context);
68023     presets = presetIndex();
68024
68025     map$$1 = rendererMap(context);
68026     context.mouse = map$$1.mouse;
68027     context.extent = map$$1.extent;
68028     context.pan = map$$1.pan;
68029     context.zoomIn = map$$1.zoomIn;
68030     context.zoomOut = map$$1.zoomOut;
68031     context.zoomInFurther = map$$1.zoomInFurther;
68032     context.zoomOutFurther = map$$1.zoomOutFurther;
68033     context.redrawEnable = map$$1.redrawEnable;
68034
68035     lodash.each(services, function(service) {
68036         if (service && typeof service.init === 'function') {
68037             service.init(context);
68038         }
68039     });
68040
68041     background.init();
68042     presets.init();
68043     areaKeys = presets.areaKeys();
68044
68045
68046     return utilRebind(context, dispatch$$1, 'on');
68047 }
68048
68049 function osmWay() {
68050     if (!(this instanceof osmWay)) {
68051         return (new osmWay()).initialize(arguments);
68052     } else if (arguments.length) {
68053         this.initialize(arguments);
68054     }
68055 }
68056
68057
68058 osmEntity$$1.way = osmWay;
68059
68060 osmWay.prototype = Object.create(osmEntity$$1.prototype);
68061
68062
68063 lodash.extend(osmWay.prototype, {
68064     type: 'way',
68065     nodes: [],
68066
68067
68068     copy: function(resolver, copies) {
68069         if (copies[this.id])
68070             return copies[this.id];
68071
68072         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
68073
68074         var nodes = this.nodes.map(function(id) {
68075             return resolver.entity(id).copy(resolver, copies).id;
68076         });
68077
68078         copy = copy.update({ nodes: nodes });
68079         copies[this.id] = copy;
68080
68081         return copy;
68082     },
68083
68084
68085     extent: function(resolver) {
68086         return resolver.transient(this, 'extent', function() {
68087             var extent$$1 = geoExtent$$1();
68088             for (var i = 0; i < this.nodes.length; i++) {
68089                 var node = resolver.hasEntity(this.nodes[i]);
68090                 if (node) {
68091                     extent$$1._extend(node.extent());
68092                 }
68093             }
68094             return extent$$1;
68095         });
68096     },
68097
68098
68099     first: function() {
68100         return this.nodes[0];
68101     },
68102
68103
68104     last: function() {
68105         return this.nodes[this.nodes.length - 1];
68106     },
68107
68108
68109     contains: function(node) {
68110         return this.nodes.indexOf(node) >= 0;
68111     },
68112
68113
68114     affix: function(node) {
68115         if (this.nodes[0] === node) return 'prefix';
68116         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
68117     },
68118
68119
68120     layer: function() {
68121         // explicit layer tag, clamp between -10, 10..
68122         if (isFinite(this.tags.layer)) {
68123             return Math.max(-10, Math.min(+(this.tags.layer), 10));
68124         }
68125
68126         // implied layer tag..
68127         if (this.tags.location === 'overground') return 1;
68128         if (this.tags.location === 'underground') return -1;
68129         if (this.tags.location === 'underwater') return -10;
68130
68131         if (this.tags.power === 'line') return 10;
68132         if (this.tags.power === 'minor_line') return 10;
68133         if (this.tags.aerialway) return 10;
68134         if (this.tags.bridge) return 1;
68135         if (this.tags.cutting) return -1;
68136         if (this.tags.tunnel) return -1;
68137         if (this.tags.waterway) return -1;
68138         if (this.tags.man_made === 'pipeline') return -10;
68139         if (this.tags.boundary) return -10;
68140         return 0;
68141     },
68142
68143
68144     isOneWay: function() {
68145         // explicit oneway tag..
68146         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
68147         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
68148
68149         // implied oneway tag..
68150         for (var key in this.tags) {
68151             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
68152                 return true;
68153         }
68154         return false;
68155     },
68156
68157
68158     lanes: function() {
68159         return osmLanes(this);
68160     },
68161
68162
68163     isClosed: function() {
68164         return this.nodes.length > 1 && this.first() === this.last();
68165     },
68166
68167
68168     isConvex: function(resolver) {
68169         if (!this.isClosed() || this.isDegenerate()) return null;
68170
68171         var nodes = lodash.uniq(resolver.childNodes(this)),
68172             coords = lodash.map(nodes, 'loc'),
68173             curr = 0, prev = 0;
68174
68175         for (var i = 0; i < coords.length; i++) {
68176             var o = coords[(i+1) % coords.length],
68177                 a = coords[i],
68178                 b = coords[(i+2) % coords.length],
68179                 res = geoCross(o, a, b);
68180
68181             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
68182             if (curr === 0) {
68183                 continue;
68184             } else if (prev && curr !== prev) {
68185                 return false;
68186             }
68187             prev = curr;
68188         }
68189         return true;
68190     },
68191
68192
68193     isArea: function() {
68194         if (this.tags.area === 'yes')
68195             return true;
68196         if (!this.isClosed() || this.tags.area === 'no')
68197             return false;
68198         for (var key in this.tags) {
68199             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
68200                 return true;
68201             }
68202         }
68203         return false;
68204     },
68205
68206
68207     isDegenerate: function() {
68208         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
68209     },
68210
68211
68212     areAdjacent: function(n1, n2) {
68213         for (var i = 0; i < this.nodes.length; i++) {
68214             if (this.nodes[i] === n1) {
68215                 if (this.nodes[i - 1] === n2) return true;
68216                 if (this.nodes[i + 1] === n2) return true;
68217             }
68218         }
68219         return false;
68220     },
68221
68222
68223     geometry: function(graph) {
68224         return graph.transient(this, 'geometry', function() {
68225             return this.isArea() ? 'area' : 'line';
68226         });
68227     },
68228
68229
68230     // If this way is not closed, append the beginning node to the end of the nodelist to close it.
68231     close: function() {
68232         if (this.isClosed() || !this.nodes.length) return this;
68233
68234         var nodes = this.nodes.slice();
68235         nodes = nodes.filter(noRepeatNodes);
68236         nodes.push(nodes[0]);
68237         return this.update({ nodes: nodes });
68238     },
68239
68240
68241     // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
68242     unclose: function() {
68243         if (!this.isClosed()) return this;
68244
68245         var nodes = this.nodes.slice(),
68246             connector = this.first(),
68247             i = nodes.length - 1;
68248
68249         // remove trailing connectors..
68250         while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68251             nodes.splice(i, 1);
68252             i = nodes.length - 1;
68253         }
68254
68255         nodes = nodes.filter(noRepeatNodes);
68256         return this.update({ nodes: nodes });
68257     },
68258
68259
68260     // Adds a node (id) in front of the node which is currently at position index.
68261     // If index is undefined, the node will be added to the end of the way for linear ways,
68262     //   or just before the final connecting node for circular ways.
68263     // Consecutive duplicates are eliminated including existing ones.
68264     // Circularity is always preserved when adding a node.
68265     addNode: function(id, index) {
68266         var nodes = this.nodes.slice(),
68267             isClosed = this.isClosed(),
68268             max$$1 = isClosed ? nodes.length - 1 : nodes.length;
68269
68270         if (index === undefined) {
68271             index = max$$1;
68272         }
68273
68274         if (index < 0 || index > max$$1) {
68275             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68276         }
68277
68278         // If this is a closed way, remove all connector nodes except the first one
68279         // (there may be duplicates) and adjust index if necessary..
68280         if (isClosed) {
68281             var connector = this.first();
68282
68283             // leading connectors..
68284             var i = 1;
68285             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68286                 nodes.splice(i, 1);
68287                 if (index > i) index--;
68288             }
68289
68290             // trailing connectors..
68291             i = nodes.length - 1;
68292             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68293                 nodes.splice(i, 1);
68294                 if (index > i) index--;
68295                 i = nodes.length - 1;
68296             }
68297         }
68298
68299         nodes.splice(index, 0, id);
68300         nodes = nodes.filter(noRepeatNodes);
68301
68302         // If the way was closed before, append a connector node to keep it closed..
68303         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68304             nodes.push(nodes[0]);
68305         }
68306
68307         return this.update({ nodes: nodes });
68308     },
68309
68310
68311     // Replaces the node which is currently at position index with the given node (id).
68312     // Consecutive duplicates are eliminated including existing ones.
68313     // Circularity is preserved when updating a node.
68314     updateNode: function(id, index) {
68315         var nodes = this.nodes.slice(),
68316             isClosed = this.isClosed(),
68317             max$$1 = nodes.length - 1;
68318
68319         if (index === undefined || index < 0 || index > max$$1) {
68320             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68321         }
68322
68323         // If this is a closed way, remove all connector nodes except the first one
68324         // (there may be duplicates) and adjust index if necessary..
68325         if (isClosed) {
68326             var connector = this.first();
68327
68328             // leading connectors..
68329             var i = 1;
68330             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68331                 nodes.splice(i, 1);
68332                 if (index > i) index--;
68333             }
68334
68335             // trailing connectors..
68336             i = nodes.length - 1;
68337             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68338                 nodes.splice(i, 1);
68339                 if (index === i) index = 0;  // update leading connector instead
68340                 i = nodes.length - 1;
68341             }
68342         }
68343
68344         nodes.splice(index, 1, id);
68345         nodes = nodes.filter(noRepeatNodes);
68346
68347         // If the way was closed before, append a connector node to keep it closed..
68348         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68349             nodes.push(nodes[0]);
68350         }
68351
68352         return this.update({nodes: nodes});
68353     },
68354
68355
68356     // Replaces each occurrence of node id needle with replacement.
68357     // Consecutive duplicates are eliminated including existing ones.
68358     // Circularity is preserved.
68359     replaceNode: function(needle, replacement) {
68360         var nodes = this.nodes.slice(),
68361             isClosed = this.isClosed();
68362
68363         for (var i = 0; i < nodes.length; i++) {
68364             if (nodes[i] === needle) {
68365                 nodes[i] = replacement;
68366             }
68367         }
68368
68369         nodes = nodes.filter(noRepeatNodes);
68370
68371         // If the way was closed before, append a connector node to keep it closed..
68372         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68373             nodes.push(nodes[0]);
68374         }
68375
68376         return this.update({nodes: nodes});
68377     },
68378
68379
68380     // Removes each occurrence of node id needle with replacement.
68381     // Consecutive duplicates are eliminated including existing ones.
68382     // Circularity is preserved.
68383     removeNode: function(id) {
68384         var nodes = this.nodes.slice(),
68385             isClosed = this.isClosed();
68386
68387         nodes = nodes
68388             .filter(function(node) { return node !== id; })
68389             .filter(noRepeatNodes);
68390
68391         // If the way was closed before, append a connector node to keep it closed..
68392         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68393             nodes.push(nodes[0]);
68394         }
68395
68396         return this.update({nodes: nodes});
68397     },
68398
68399
68400     asJXON: function(changeset_id) {
68401         var r = {
68402             way: {
68403                 '@id': this.osmId(),
68404                 '@version': this.version || 0,
68405                 nd: lodash.map(this.nodes, function(id) {
68406                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
68407                 }),
68408                 tag: lodash.map(this.tags, function(v, k) {
68409                     return { keyAttributes: { k: k, v: v } };
68410                 })
68411             }
68412         };
68413         if (changeset_id) {
68414             r.way['@changeset'] = changeset_id;
68415         }
68416         return r;
68417     },
68418
68419
68420     asGeoJSON: function(resolver) {
68421         return resolver.transient(this, 'GeoJSON', function() {
68422             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
68423             if (this.isArea() && this.isClosed()) {
68424                 return {
68425                     type: 'Polygon',
68426                     coordinates: [coordinates]
68427                 };
68428             } else {
68429                 return {
68430                     type: 'LineString',
68431                     coordinates: coordinates
68432                 };
68433             }
68434         });
68435     },
68436
68437
68438     area: function(resolver) {
68439         return resolver.transient(this, 'area', function() {
68440             var nodes = resolver.childNodes(this);
68441
68442             var json$$1 = {
68443                 type: 'Polygon',
68444                 coordinates: [lodash.map(nodes, 'loc')]
68445             };
68446
68447             if (!this.isClosed() && nodes.length) {
68448                 json$$1.coordinates[0].push(nodes[0].loc);
68449             }
68450
68451             var area$$1 = area(json$$1);
68452
68453             // Heuristic for detecting counterclockwise winding order. Assumes
68454             // that OpenStreetMap polygons are not hemisphere-spanning.
68455             if (area$$1 > 2 * Math.PI) {
68456                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
68457                 area$$1 = area(json$$1);
68458             }
68459
68460             return isNaN(area$$1) ? 0 : area$$1;
68461         });
68462     }
68463 });
68464
68465
68466 // Filter function to eliminate consecutive duplicates.
68467 function noRepeatNodes(node, i, arr) {
68468     return i === 0 || node !== arr[i - 1];
68469 }
68470
68471 function osmTurn(turn) {
68472     if (!(this instanceof osmTurn))
68473         return new osmTurn(turn);
68474     lodash.extend(this, turn);
68475 }
68476
68477
68478 function osmIntersection(graph, vertexId) {
68479     var vertex = graph.entity(vertexId),
68480         parentWays = graph.parentWays(vertex),
68481         coincident = [],
68482         highways = {};
68483
68484     function addHighway(way, adjacentNodeId) {
68485         if (highways[adjacentNodeId]) {
68486             coincident.push(adjacentNodeId);
68487         } else {
68488             highways[adjacentNodeId] = way;
68489         }
68490     }
68491
68492     // Pre-split ways that would need to be split in
68493     // order to add a restriction. The real split will
68494     // happen when the restriction is added.
68495     parentWays.forEach(function(way) {
68496         if (!way.tags.highway || way.isArea() || way.isDegenerate())
68497             return;
68498
68499         var isFirst = (vertexId === way.first()),
68500             isLast = (vertexId === way.last()),
68501             isAffix = (isFirst || isLast),
68502             isClosingNode = (isFirst && isLast);
68503
68504         if (isAffix && !isClosingNode) {
68505             var index = (isFirst ? 1 : way.nodes.length - 2);
68506             addHighway(way, way.nodes[index]);
68507
68508         } else {
68509             var splitIndex, wayA, wayB, indexA, indexB;
68510             if (isClosingNode) {
68511                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
68512                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
68513                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68514                 indexA = 1;
68515                 indexB = way.nodes.length - 2;
68516             } else {
68517                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
68518                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
68519                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68520                 indexA = splitIndex - 1;
68521                 indexB = splitIndex + 1;
68522             }
68523             graph = graph.replace(wayA).replace(wayB);
68524             addHighway(wayA, way.nodes[indexA]);
68525             addHighway(wayB, way.nodes[indexB]);
68526         }
68527     });
68528
68529     // remove any ways from this intersection that are coincident
68530     // (i.e. any adjacent node used by more than one intersecting way)
68531     coincident.forEach(function (n) {
68532         delete highways[n];
68533     });
68534
68535
68536     var intersection = {
68537         highways: highways,
68538         ways: lodash.values(highways),
68539         graph: graph
68540     };
68541
68542
68543     intersection.adjacentNodeId = function(fromWayId) {
68544         return lodash.find(lodash.keys(highways), function(k) {
68545             return highways[k].id === fromWayId;
68546         });
68547     };
68548
68549
68550     intersection.turns = function(fromNodeId) {
68551         var start = highways[fromNodeId];
68552         if (!start)
68553             return [];
68554
68555         if (start.first() === vertex.id && start.tags.oneway === 'yes')
68556             return [];
68557         if (start.last() === vertex.id && start.tags.oneway === '-1')
68558             return [];
68559
68560         function withRestriction(turn) {
68561             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
68562                 if (relation.tags.type !== 'restriction')
68563                     return;
68564
68565                 var f = relation.memberByRole('from'),
68566                     t = relation.memberByRole('to'),
68567                     v = relation.memberByRole('via');
68568
68569                 if (f && f.id === turn.from.way &&
68570                     v && v.id === turn.via.node &&
68571                     t && t.id === turn.to.way) {
68572                     turn.restriction = relation.id;
68573                 } else if (/^only_/.test(relation.tags.restriction) &&
68574                     f && f.id === turn.from.way &&
68575                     v && v.id === turn.via.node &&
68576                     t && t.id !== turn.to.way) {
68577                     turn.restriction = relation.id;
68578                     turn.indirect_restriction = true;
68579                 }
68580             });
68581
68582             return osmTurn(turn);
68583         }
68584
68585
68586         var from = {
68587                 node: fromNodeId,
68588                 way: start.id.split(/-(a|b)/)[0]
68589             },
68590             via = { node: vertex.id },
68591             turns = [];
68592
68593         lodash.each(highways, function(end, adjacentNodeId) {
68594             if (end === start)
68595                 return;
68596
68597             // backward
68598             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
68599                 turns.push(withRestriction({
68600                     from: from,
68601                     via: via,
68602                     to: {
68603                         node: adjacentNodeId,
68604                         way: end.id.split(/-(a|b)/)[0]
68605                     }
68606                 }));
68607             }
68608
68609             // forward
68610             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
68611                 turns.push(withRestriction({
68612                     from: from,
68613                     via: via,
68614                     to: {
68615                         node: adjacentNodeId,
68616                         way: end.id.split(/-(a|b)/)[0]
68617                     }
68618                 }));
68619             }
68620
68621         });
68622
68623         // U-turn
68624         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
68625             turns.push(withRestriction({
68626                 from: from,
68627                 via: via,
68628                 to: from,
68629                 u: true
68630             }));
68631         }
68632
68633         return turns;
68634     };
68635
68636     return intersection;
68637 }
68638
68639
68640 function osmInferRestriction(graph, from, via, to, projection) {
68641     var fromWay = graph.entity(from.way),
68642         fromNode = graph.entity(from.node),
68643         toWay = graph.entity(to.way),
68644         toNode = graph.entity(to.node),
68645         viaNode = graph.entity(via.node),
68646         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
68647             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
68648         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
68649             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
68650         angle = geoAngle(viaNode, fromNode, projection) -
68651                 geoAngle(viaNode, toNode, projection);
68652
68653     angle = angle * 180 / Math.PI;
68654
68655     while (angle < 0)
68656         angle += 360;
68657
68658     if (fromNode === toNode)
68659         return 'no_u_turn';
68660     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
68661         return 'no_u_turn';
68662     if (angle < 158)
68663         return 'no_right_turn';
68664     if (angle > 202)
68665         return 'no_left_turn';
68666
68667     return 'no_straight_on';
68668 }
68669
68670 function actionAddMember(relationId, member, memberIndex) {
68671     return function(graph) {
68672         var relation = graph.entity(relationId);
68673
68674         if (isNaN(memberIndex) && member.type === 'way') {
68675             var members = relation.indexedMembers();
68676             members.push(member);
68677
68678             var joined = osmJoinWays(members, graph);
68679             for (var i = 0; i < joined.length; i++) {
68680                 var segment = joined[i];
68681                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
68682                     if (segment[j] !== member)
68683                         continue;
68684
68685                     if (j === 0) {
68686                         memberIndex = segment[j + 1].index;
68687                     } else if (j === segment.length - 1) {
68688                         memberIndex = segment[j - 1].index + 1;
68689                     } else {
68690                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
68691                     }
68692                 }
68693             }
68694         }
68695
68696         return graph.replace(relation.addMember(member, memberIndex));
68697     };
68698 }
68699
68700 function actionAddMidpoint(midpoint, node) {
68701     return function(graph) {
68702         graph = graph.replace(node.move(midpoint.loc));
68703
68704         var parents = lodash.intersection(
68705             graph.parentWays(graph.entity(midpoint.edge[0])),
68706             graph.parentWays(graph.entity(midpoint.edge[1])));
68707
68708         parents.forEach(function(way) {
68709             for (var i = 0; i < way.nodes.length - 1; i++) {
68710                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
68711                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
68712
68713                     // Add only one midpoint on doubled-back segments,
68714                     // turning them into self-intersections.
68715                     return;
68716                 }
68717             }
68718         });
68719
68720         return graph;
68721     };
68722 }
68723
68724 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
68725 function actionAddVertex(wayId, nodeId, index) {
68726     return function(graph) {
68727         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
68728     };
68729 }
68730
68731 function actionChangeMember(relationId, member, memberIndex) {
68732     return function(graph) {
68733         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
68734     };
68735 }
68736
68737 function actionChangePreset(entityId, oldPreset, newPreset) {
68738     return function(graph) {
68739         var entity = graph.entity(entityId),
68740             geometry = entity.geometry(graph),
68741             tags = entity.tags;
68742
68743         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
68744         if (newPreset) tags = newPreset.applyTags(tags, geometry);
68745
68746         return graph.replace(entity.update({tags: tags}));
68747     };
68748 }
68749
68750 function actionChangeTags(entityId, tags) {
68751     return function(graph) {
68752         var entity = graph.entity(entityId);
68753         return graph.replace(entity.update({tags: tags}));
68754     };
68755 }
68756
68757 function actionCircularize(wayId, projection, maxAngle) {
68758     maxAngle = (maxAngle || 20) * Math.PI / 180;
68759
68760
68761     var action = function(graph, t) {
68762         if (t === null || !isFinite(t)) t = 1;
68763         t = Math.min(Math.max(+t, 0), 1);
68764
68765         var way = graph.entity(wayId),
68766             origNodes = {};
68767
68768         graph.childNodes(way).forEach(function(node) {
68769             if (!origNodes[node.id]) origNodes[node.id] = node;
68770         });
68771
68772         if (!way.isConvex(graph)) {
68773             graph = action.makeConvex(graph);
68774         }
68775
68776         var nodes = lodash.uniq(graph.childNodes(way)),
68777             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
68778             points = nodes.map(function(n) { return projection(n.loc); }),
68779             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
68780             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
68781             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
68782             sign = d3polygonArea(points) > 0 ? 1 : -1,
68783             ids;
68784
68785         // we need atleast two key nodes for the algorithm to work
68786         if (!keyNodes.length) {
68787             keyNodes = [nodes[0]];
68788             keyPoints = [points[0]];
68789         }
68790
68791         if (keyNodes.length === 1) {
68792             var index = nodes.indexOf(keyNodes[0]),
68793                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
68794
68795             keyNodes.push(nodes[oppositeIndex]);
68796             keyPoints.push(points[oppositeIndex]);
68797         }
68798
68799         // key points and nodes are those connected to the ways,
68800         // they are projected onto the circle, inbetween nodes are moved
68801         // to constant intervals between key nodes, extra inbetween nodes are
68802         // added if necessary.
68803         for (var i = 0; i < keyPoints.length; i++) {
68804             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
68805                 startNode = keyNodes[i],
68806                 endNode = keyNodes[nextKeyNodeIndex],
68807                 startNodeIndex = nodes.indexOf(startNode),
68808                 endNodeIndex = nodes.indexOf(endNode),
68809                 numberNewPoints = -1,
68810                 indexRange = endNodeIndex - startNodeIndex,
68811                 nearNodes = {},
68812                 inBetweenNodes = [],
68813                 startAngle, endAngle, totalAngle, eachAngle,
68814                 angle, loc, node, origNode, j;
68815
68816             if (indexRange < 0) {
68817                 indexRange += nodes.length;
68818             }
68819
68820             // position this key node
68821             var distance = geoEuclideanDistance(centroid, keyPoints[i]);
68822             if (distance === 0) { distance = 1e-4; }
68823             keyPoints[i] = [
68824                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
68825                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius
68826             ];
68827             loc = projection.invert(keyPoints[i]);
68828             node = keyNodes[i];
68829             origNode = origNodes[node.id];
68830             node = node.move(geoInterp(origNode.loc, loc, t));
68831             graph = graph.replace(node);
68832
68833             // figure out the between delta angle we want to match to
68834             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
68835             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
68836             totalAngle = endAngle - startAngle;
68837
68838             // detects looping around -pi/pi
68839             if (totalAngle * sign > 0) {
68840                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
68841             }
68842
68843             do {
68844                 numberNewPoints++;
68845                 eachAngle = totalAngle / (indexRange + numberNewPoints);
68846             } while (Math.abs(eachAngle) > maxAngle);
68847
68848
68849             // move existing nodes
68850             for (j = 1; j < indexRange; j++) {
68851                 angle = startAngle + j * eachAngle;
68852                 loc = projection.invert([
68853                     centroid[0] + Math.cos(angle) * radius,
68854                     centroid[1] + Math.sin(angle) * radius
68855                 ]);
68856
68857                 node = nodes[(j + startNodeIndex) % nodes.length];
68858                 origNode = origNodes[node.id];
68859                 nearNodes[node.id] = angle;
68860
68861                 node = node.move(geoInterp(origNode.loc, loc, t));
68862                 graph = graph.replace(node);
68863             }
68864
68865             // add new inbetween nodes if necessary
68866             for (j = 0; j < numberNewPoints; j++) {
68867                 angle = startAngle + (indexRange + j) * eachAngle;
68868                 loc = projection.invert([
68869                     centroid[0] + Math.cos(angle) * radius,
68870                     centroid[1] + Math.sin(angle) * radius
68871                 ]);
68872
68873                 // choose a nearnode to use as the original
68874                 var min$$1 = Infinity;
68875                 for (var nodeId in nearNodes) {
68876                     var nearAngle = nearNodes[nodeId],
68877                         dist = Math.abs(nearAngle - angle);
68878                     if (dist < min$$1) {
68879                         dist = min$$1;
68880                         origNode = origNodes[nodeId];
68881                     }
68882                 }
68883
68884                 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
68885                 graph = graph.replace(node);
68886
68887                 nodes.splice(endNodeIndex + j, 0, node);
68888                 inBetweenNodes.push(node.id);
68889             }
68890
68891             // Check for other ways that share these keyNodes..
68892             // If keyNodes are adjacent in both ways,
68893             // we can add inBetween nodes to that shared way too..
68894             if (indexRange === 1 && inBetweenNodes.length) {
68895                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
68896                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
68897                     wayDirection1 = (endIndex1 - startIndex1);
68898                 if (wayDirection1 < -1) { wayDirection1 = 1; }
68899
68900                 /* eslint-disable no-loop-func */
68901                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
68902                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
68903                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
68904                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
68905                             wayDirection2 = (endIndex2 - startIndex2),
68906                             insertAt = endIndex2;
68907                         if (wayDirection2 < -1) { wayDirection2 = 1; }
68908
68909                         if (wayDirection1 !== wayDirection2) {
68910                             inBetweenNodes.reverse();
68911                             insertAt = startIndex2;
68912                         }
68913                         for (j = 0; j < inBetweenNodes.length; j++) {
68914                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
68915                         }
68916                         graph = graph.replace(sharedWay);
68917                     }
68918                 });
68919                 /* eslint-enable no-loop-func */
68920             }
68921
68922         }
68923
68924         // update the way to have all the new nodes
68925         ids = nodes.map(function(n) { return n.id; });
68926         ids.push(ids[0]);
68927
68928         way = way.update({nodes: ids});
68929         graph = graph.replace(way);
68930
68931         return graph;
68932     };
68933
68934
68935     action.makeConvex = function(graph) {
68936         var way = graph.entity(wayId),
68937             nodes = lodash.uniq(graph.childNodes(way)),
68938             points = nodes.map(function(n) { return projection(n.loc); }),
68939             sign = d3polygonArea(points) > 0 ? 1 : -1,
68940             hull = d3polygonHull(points);
68941
68942         // D3 convex hulls go counterclockwise..
68943         if (sign === -1) {
68944             nodes.reverse();
68945             points.reverse();
68946         }
68947
68948         for (var i = 0; i < hull.length - 1; i++) {
68949             var startIndex = points.indexOf(hull[i]),
68950                 endIndex = points.indexOf(hull[i+1]),
68951                 indexRange = (endIndex - startIndex);
68952
68953             if (indexRange < 0) {
68954                 indexRange += nodes.length;
68955             }
68956
68957             // move interior nodes to the surface of the convex hull..
68958             for (var j = 1; j < indexRange; j++) {
68959                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
68960                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
68961                 graph = graph.replace(node);
68962             }
68963         }
68964         return graph;
68965     };
68966
68967
68968     action.disabled = function(graph) {
68969         if (!graph.entity(wayId).isClosed())
68970             return 'not_closed';
68971     };
68972
68973
68974     action.transitionable = true;
68975
68976
68977     return action;
68978 }
68979
68980 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
68981 function actionDeleteWay(wayId) {
68982
68983
68984     function canDeleteNode(node, graph) {
68985         return !graph.parentWays(node).length &&
68986             !graph.parentRelations(node).length &&
68987             !node.hasInterestingTags();
68988     }
68989
68990
68991     var action = function(graph) {
68992         var way = graph.entity(wayId);
68993
68994         graph.parentRelations(way)
68995             .forEach(function(parent) {
68996                 parent = parent.removeMembersWithID(wayId);
68997                 graph = graph.replace(parent);
68998
68999                 if (parent.isDegenerate()) {
69000                     graph = actionDeleteRelation(parent.id)(graph);
69001                 }
69002             });
69003
69004         lodash.uniq(way.nodes).forEach(function(nodeId) {
69005             graph = graph.replace(way.removeNode(nodeId));
69006
69007             var node = graph.entity(nodeId);
69008             if (canDeleteNode(node, graph)) {
69009                 graph = graph.remove(node);
69010             }
69011         });
69012
69013         return graph.remove(way);
69014     };
69015
69016
69017     return action;
69018 }
69019
69020 function actionDeleteMultiple(ids) {
69021     var actions = {
69022         way: actionDeleteWay,
69023         node: actionDeleteNode,
69024         relation: actionDeleteRelation
69025     };
69026
69027
69028     var action = function(graph) {
69029         ids.forEach(function(id) {
69030             if (graph.hasEntity(id)) { // It may have been deleted aready.
69031                 graph = actions[graph.entity(id).type](id)(graph);
69032             }
69033         });
69034
69035         return graph;
69036     };
69037
69038
69039     return action;
69040 }
69041
69042 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
69043 function actionDeleteRelation(relationId) {
69044
69045
69046     function canDeleteEntity(entity, graph) {
69047         return !graph.parentWays(entity).length &&
69048             !graph.parentRelations(entity).length &&
69049             !entity.hasInterestingTags();
69050     }
69051
69052
69053     var action = function(graph) {
69054         var relation = graph.entity(relationId);
69055
69056         graph.parentRelations(relation)
69057             .forEach(function(parent) {
69058                 parent = parent.removeMembersWithID(relationId);
69059                 graph = graph.replace(parent);
69060
69061                 if (parent.isDegenerate()) {
69062                     graph = actionDeleteRelation(parent.id)(graph);
69063                 }
69064             });
69065
69066         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
69067             graph = graph.replace(relation.removeMembersWithID(memberId));
69068
69069             var entity = graph.entity(memberId);
69070             if (canDeleteEntity(entity, graph)) {
69071                 graph = actionDeleteMultiple([memberId])(graph);
69072             }
69073         });
69074
69075         return graph.remove(relation);
69076     };
69077
69078
69079     return action;
69080 }
69081
69082 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
69083 function actionDeleteNode(nodeId) {
69084     var action = function(graph) {
69085         var node = graph.entity(nodeId);
69086
69087         graph.parentWays(node)
69088             .forEach(function(parent) {
69089                 parent = parent.removeNode(nodeId);
69090                 graph = graph.replace(parent);
69091
69092                 if (parent.isDegenerate()) {
69093                     graph = actionDeleteWay(parent.id)(graph);
69094                 }
69095             });
69096
69097         graph.parentRelations(node)
69098             .forEach(function(parent) {
69099                 parent = parent.removeMembersWithID(nodeId);
69100                 graph = graph.replace(parent);
69101
69102                 if (parent.isDegenerate()) {
69103                     graph = actionDeleteRelation(parent.id)(graph);
69104                 }
69105             });
69106
69107         return graph.remove(node);
69108     };
69109
69110
69111     return action;
69112 }
69113
69114 // Connect the ways at the given nodes.
69115 //
69116 // The last node will survive. All other nodes will be replaced with
69117 // the surviving node in parent ways, and then removed.
69118 //
69119 // Tags and relation memberships of of non-surviving nodes are merged
69120 // to the survivor.
69121 //
69122 // This is the inverse of `iD.actionDisconnect`.
69123 //
69124 // Reference:
69125 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
69126 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
69127 //
69128 function actionConnect(nodeIds) {
69129     return function(graph) {
69130         var survivor = graph.entity(lodash.last(nodeIds));
69131
69132         for (var i = 0; i < nodeIds.length - 1; i++) {
69133             var node = graph.entity(nodeIds[i]);
69134
69135             /* eslint-disable no-loop-func */
69136             graph.parentWays(node).forEach(function(parent) {
69137                 if (!parent.areAdjacent(node.id, survivor.id)) {
69138                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
69139                 }
69140             });
69141
69142             graph.parentRelations(node).forEach(function(parent) {
69143                 graph = graph.replace(parent.replaceMember(node, survivor));
69144             });
69145             /* eslint-enable no-loop-func */
69146
69147             survivor = survivor.mergeTags(node.tags);
69148             graph = actionDeleteNode(node.id)(graph);
69149         }
69150
69151         graph = graph.replace(survivor);
69152
69153         return graph;
69154     };
69155 }
69156
69157 function actionCopyEntities(ids, fromGraph) {
69158     var copies = {};
69159
69160
69161     var action = function(graph) {
69162         ids.forEach(function(id) {
69163             fromGraph.entity(id).copy(fromGraph, copies);
69164         });
69165
69166         for (var id in copies) {
69167             graph = graph.replace(copies[id]);
69168         }
69169
69170         return graph;
69171     };
69172
69173
69174     action.copies = function() {
69175         return copies;
69176     };
69177
69178
69179     return action;
69180 }
69181
69182 function actionDeleteMember(relationId, memberIndex) {
69183     return function(graph) {
69184         var relation = graph.entity(relationId)
69185             .removeMember(memberIndex);
69186
69187         graph = graph.replace(relation);
69188
69189         if (relation.isDegenerate())
69190             graph = actionDeleteRelation(relation.id)(graph);
69191
69192         return graph;
69193     };
69194 }
69195
69196 function actionDeprecateTags(entityId) {
69197
69198     return function(graph) {
69199         var entity = graph.entity(entityId),
69200             newtags = lodash.clone(entity.tags),
69201             change = false,
69202             rule;
69203
69204         // This handles dataDeprecated tags with a single condition
69205         for (var i = 0; i < dataDeprecated.length; i++) {
69206
69207             rule = dataDeprecated[i];
69208             var match = lodash.toPairs(rule.old)[0],
69209                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
69210
69211             if (entity.tags[match[0]] && match[1] === '*') {
69212
69213                 var value = entity.tags[match[0]];
69214                 if (replacements && !newtags[replacements[0][0]]) {
69215                     newtags[replacements[0][0]] = value;
69216                 }
69217                 delete newtags[match[0]];
69218                 change = true;
69219
69220             } else if (entity.tags[match[0]] === match[1]) {
69221                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
69222                 change = true;
69223             }
69224         }
69225
69226         if (change) {
69227             return graph.replace(entity.update({tags: newtags}));
69228         } else {
69229             return graph;
69230         }
69231     };
69232 }
69233
69234 function actionDiscardTags(difference) {
69235
69236     return function(graph) {
69237         function discardTags(entity) {
69238             if (!lodash.isEmpty(entity.tags)) {
69239                 var tags = {};
69240                 lodash.each(entity.tags, function(v, k) {
69241                     if (v) tags[k] = v;
69242                 });
69243
69244                 graph = graph.replace(entity.update({
69245                     tags: lodash.omit(tags, dataDiscarded)
69246                 }));
69247             }
69248         }
69249
69250         difference.modified().forEach(discardTags);
69251         difference.created().forEach(discardTags);
69252
69253         return graph;
69254     };
69255 }
69256
69257 // Disconect the ways at the given node.
69258 //
69259 // Optionally, disconnect only the given ways.
69260 //
69261 // For testing convenience, accepts an ID to assign to the (first) new node.
69262 // Normally, this will be undefined and the way will automatically
69263 // be assigned a new ID.
69264 //
69265 // This is the inverse of `iD.actionConnect`.
69266 //
69267 // Reference:
69268 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
69269 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
69270 //
69271 function actionDisconnect(nodeId, newNodeId) {
69272     var wayIds;
69273
69274
69275     var action = function(graph) {
69276         var node = graph.entity(nodeId),
69277             connections = action.connections(graph);
69278
69279         connections.forEach(function(connection) {
69280             var way = graph.entity(connection.wayID),
69281                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
69282
69283             graph = graph.replace(newNode);
69284             if (connection.index === 0 && way.isArea()) {
69285                 // replace shared node with shared node..
69286                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
69287             } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
69288                 // replace closing node with new new node..
69289                 graph = graph.replace(way.unclose().addNode(newNode.id));
69290             } else {
69291                 // replace shared node with multiple new nodes..
69292                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
69293             }
69294         });
69295
69296         return graph;
69297     };
69298
69299
69300     action.connections = function(graph) {
69301         var candidates = [],
69302             keeping = false,
69303             parentWays = graph.parentWays(graph.entity(nodeId));
69304
69305         parentWays.forEach(function(way) {
69306             if (wayIds && wayIds.indexOf(way.id) === -1) {
69307                 keeping = true;
69308                 return;
69309             }
69310             if (way.isArea() && (way.nodes[0] === nodeId)) {
69311                 candidates.push({ wayID: way.id, index: 0 });
69312             } else {
69313                 way.nodes.forEach(function(waynode, index) {
69314                     if (waynode === nodeId) {
69315                         candidates.push({ wayID: way.id, index: index });
69316                     }
69317                 });
69318             }
69319         });
69320
69321         return keeping ? candidates : candidates.slice(1);
69322     };
69323
69324
69325     action.disabled = function(graph) {
69326         var connections = action.connections(graph);
69327         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
69328             return 'not_connected';
69329
69330         var parentWays = graph.parentWays(graph.entity(nodeId)),
69331             seenRelationIds = {},
69332             sharedRelation;
69333
69334         parentWays.forEach(function(way) {
69335             if (wayIds && wayIds.indexOf(way.id) === -1)
69336                 return;
69337
69338             var relations = graph.parentRelations(way);
69339             relations.forEach(function(relation) {
69340                 if (relation.id in seenRelationIds) {
69341                     sharedRelation = relation;
69342                 } else {
69343                     seenRelationIds[relation.id] = true;
69344                 }
69345             });
69346         });
69347
69348         if (sharedRelation)
69349             return 'relation';
69350     };
69351
69352
69353     action.limitWays = function(_) {
69354         if (!arguments.length) return wayIds;
69355         wayIds = _;
69356         return action;
69357     };
69358
69359
69360     return action;
69361 }
69362
69363 // Join ways at the end node they share.
69364 //
69365 // This is the inverse of `iD.actionSplit`.
69366 //
69367 // Reference:
69368 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
69369 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
69370 //
69371 function actionJoin(ids) {
69372
69373     function groupEntitiesByGeometry(graph) {
69374         var entities = ids.map(function(id) { return graph.entity(id); });
69375         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69376     }
69377
69378
69379     var action = function(graph) {
69380         var ways = ids.map(graph.entity, graph),
69381             survivor = ways[0];
69382
69383         // Prefer to keep an existing way.
69384         for (var i = 0; i < ways.length; i++) {
69385             if (!ways[i].isNew()) {
69386                 survivor = ways[i];
69387                 break;
69388             }
69389         }
69390
69391         var joined = osmJoinWays(ways, graph)[0];
69392
69393         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
69394         graph = graph.replace(survivor);
69395
69396         joined.forEach(function(way) {
69397             if (way.id === survivor.id)
69398                 return;
69399
69400             graph.parentRelations(way).forEach(function(parent) {
69401                 graph = graph.replace(parent.replaceMember(way, survivor));
69402             });
69403
69404             survivor = survivor.mergeTags(way.tags);
69405
69406             graph = graph.replace(survivor);
69407             graph = actionDeleteWay(way.id)(graph);
69408         });
69409
69410         return graph;
69411     };
69412
69413
69414     action.disabled = function(graph) {
69415         var geometries = groupEntitiesByGeometry(graph);
69416         if (ids.length < 2 || ids.length !== geometries.line.length)
69417             return 'not_eligible';
69418
69419         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
69420         if (joined.length > 1)
69421             return 'not_adjacent';
69422
69423         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
69424             relation,
69425             tags = {},
69426             conflicting = false;
69427
69428         joined[0].forEach(function(way) {
69429             var parents = graph.parentRelations(way);
69430             parents.forEach(function(parent) {
69431                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
69432                     relation = parent;
69433             });
69434
69435             for (var k in way.tags) {
69436                 if (!(k in tags)) {
69437                     tags[k] = way.tags[k];
69438                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
69439                     conflicting = true;
69440                 }
69441             }
69442         });
69443
69444         if (relation)
69445             return 'restriction';
69446
69447         if (conflicting)
69448             return 'conflicting_tags';
69449     };
69450
69451
69452     return action;
69453 }
69454
69455 function actionMerge(ids) {
69456
69457     function groupEntitiesByGeometry(graph) {
69458         var entities = ids.map(function(id) { return graph.entity(id); });
69459         return lodash.extend({point: [], area: [], line: [], relation: []},
69460             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69461     }
69462
69463
69464     var action = function(graph) {
69465         var geometries = groupEntitiesByGeometry(graph),
69466             target = geometries.area[0] || geometries.line[0],
69467             points = geometries.point;
69468
69469         points.forEach(function(point) {
69470             target = target.mergeTags(point.tags);
69471             graph = graph.replace(target);
69472
69473             graph.parentRelations(point).forEach(function(parent) {
69474                 graph = graph.replace(parent.replaceMember(point, target));
69475             });
69476
69477             var nodes = lodash.uniq(graph.childNodes(target)),
69478                 removeNode = point;
69479
69480             for (var i = 0; i < nodes.length; i++) {
69481                 var node = nodes[i];
69482                 if (graph.parentWays(node).length > 1 ||
69483                     graph.parentRelations(node).length ||
69484                     node.hasInterestingTags()) {
69485                     continue;
69486                 }
69487
69488                 // Found an uninteresting child node on the target way.
69489                 // Move orig point into its place to preserve point's history. #3683
69490                 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
69491                 target = target.replaceNode(node.id, point.id);
69492                 graph = graph.replace(target);
69493                 removeNode = node;
69494                 break;
69495             }
69496
69497             graph = graph.remove(removeNode);
69498         });
69499
69500         return graph;
69501     };
69502
69503
69504     action.disabled = function(graph) {
69505         var geometries = groupEntitiesByGeometry(graph);
69506         if (geometries.point.length === 0 ||
69507             (geometries.area.length + geometries.line.length) !== 1 ||
69508             geometries.relation.length !== 0)
69509             return 'not_eligible';
69510     };
69511
69512
69513     return action;
69514 }
69515
69516 function actionMergePolygon(ids, newRelationId) {
69517
69518     function groupEntities(graph) {
69519         var entities = ids.map(function (id) { return graph.entity(id); });
69520         return lodash.extend({
69521                 closedWay: [],
69522                 multipolygon: [],
69523                 other: []
69524             }, lodash.groupBy(entities, function(entity) {
69525                 if (entity.type === 'way' && entity.isClosed()) {
69526                     return 'closedWay';
69527                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
69528                     return 'multipolygon';
69529                 } else {
69530                     return 'other';
69531                 }
69532             }));
69533     }
69534
69535
69536     var action = function(graph) {
69537         var entities = groupEntities(graph);
69538
69539         // An array representing all the polygons that are part of the multipolygon.
69540         //
69541         // Each element is itself an array of objects with an id property, and has a
69542         // locs property which is an array of the locations forming the polygon.
69543         var polygons = entities.multipolygon.reduce(function(polygons, m) {
69544             return polygons.concat(osmJoinWays(m.members, graph));
69545         }, []).concat(entities.closedWay.map(function(d) {
69546             var member = [{id: d.id}];
69547             member.nodes = graph.childNodes(d);
69548             return member;
69549         }));
69550
69551         // contained is an array of arrays of boolean values,
69552         // where contained[j][k] is true iff the jth way is
69553         // contained by the kth way.
69554         var contained = polygons.map(function(w, i) {
69555             return polygons.map(function(d, n) {
69556                 if (i === n) return null;
69557                 return geoPolygonContainsPolygon(
69558                     lodash.map(d.nodes, 'loc'),
69559                     lodash.map(w.nodes, 'loc'));
69560             });
69561         });
69562
69563         // Sort all polygons as either outer or inner ways
69564         var members = [],
69565             outer = true;
69566
69567         while (polygons.length) {
69568             extractUncontained(polygons);
69569             polygons = polygons.filter(isContained);
69570             contained = contained.filter(isContained).map(filterContained);
69571         }
69572
69573         function isContained(d, i) {
69574             return lodash.some(contained[i]);
69575         }
69576
69577         function filterContained(d) {
69578             return d.filter(isContained);
69579         }
69580
69581         function extractUncontained(polygons) {
69582             polygons.forEach(function(d, i) {
69583                 if (!isContained(d, i)) {
69584                     d.forEach(function(member) {
69585                         members.push({
69586                             type: 'way',
69587                             id: member.id,
69588                             role: outer ? 'outer' : 'inner'
69589                         });
69590                     });
69591                 }
69592             });
69593             outer = !outer;
69594         }
69595
69596         // Move all tags to one relation
69597         var relation = entities.multipolygon[0] ||
69598             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
69599
69600         entities.multipolygon.slice(1).forEach(function(m) {
69601             relation = relation.mergeTags(m.tags);
69602             graph = graph.remove(m);
69603         });
69604
69605         entities.closedWay.forEach(function(way) {
69606             function isThisOuter(m) {
69607                 return m.id === way.id && m.role !== 'inner';
69608             }
69609             if (members.some(isThisOuter)) {
69610                 relation = relation.mergeTags(way.tags);
69611                 graph = graph.replace(way.update({ tags: {} }));
69612             }
69613         });
69614
69615         return graph.replace(relation.update({
69616             members: members,
69617             tags: lodash.omit(relation.tags, 'area')
69618         }));
69619     };
69620
69621
69622     action.disabled = function(graph) {
69623         var entities = groupEntities(graph);
69624         if (entities.other.length > 0 ||
69625             entities.closedWay.length + entities.multipolygon.length < 2)
69626             return 'not_eligible';
69627         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
69628             return 'incomplete_relation';
69629     };
69630
69631
69632     return action;
69633 }
69634
69635 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
69636 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
69637 //
69638 // Permission is hereby granted, free of charge, to any person
69639 // obtaining a copy of this software and associated documentation files
69640 // (the "Software"), to deal in the Software without restriction,
69641 // including without limitation the rights to use, copy, modify, merge,
69642 // publish, distribute, sublicense, and/or sell copies of the Software,
69643 // and to permit persons to whom the Software is furnished to do so,
69644 // subject to the following conditions:
69645 //
69646 // The above copyright notice and this permission notice shall be
69647 // included in all copies or substantial portions of the Software.
69648 //
69649 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
69650 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69651 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69652 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
69653 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
69654 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
69655 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69656 // SOFTWARE.
69657
69658 // source:  https://bitbucket.org/lshift/synchrotron/src
69659 function longest_common_subsequence(file1, file2) {
69660     /* Text diff algorithm following Hunt and McIlroy 1976.
69661      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
69662      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
69663      * http://www.cs.dartmouth.edu/~doug/
69664      *
69665      * Expects two arrays of strings.
69666      */
69667     var equivalenceClasses;
69668     var file2indices;
69669     var newCandidate;
69670     var candidates;
69671     var line;
69672     var c, i, j, jX, r, s;
69673
69674     equivalenceClasses = {};
69675     for (j = 0; j < file2.length; j++) {
69676         line = file2[j];
69677         if (equivalenceClasses[line]) {
69678             equivalenceClasses[line].push(j);
69679         } else {
69680             equivalenceClasses[line] = [j];
69681         }
69682     }
69683
69684     candidates = [{file1index: -1,
69685                    file2index: -1,
69686                    chain: null}];
69687
69688     for (i = 0; i < file1.length; i++) {
69689         line = file1[i];
69690         file2indices = equivalenceClasses[line] || [];
69691
69692         r = 0;
69693         c = candidates[0];
69694
69695         for (jX = 0; jX < file2indices.length; jX++) {
69696             j = file2indices[jX];
69697
69698             for (s = 0; s < candidates.length; s++) {
69699                 if ((candidates[s].file2index < j) &&
69700                     ((s === candidates.length - 1) ||
69701                      (candidates[s + 1].file2index > j)))
69702                     break;
69703             }
69704
69705             if (s < candidates.length) {
69706                 newCandidate = {file1index: i,
69707                                 file2index: j,
69708                                 chain: candidates[s]};
69709                 if (r === candidates.length) {
69710                     candidates.push(c);
69711                 } else {
69712                     candidates[r] = c;
69713                 }
69714                 r = s + 1;
69715                 c = newCandidate;
69716                 if (r === candidates.length) {
69717                     break; // no point in examining further (j)s
69718                 }
69719             }
69720         }
69721
69722         candidates[r] = c;
69723     }
69724
69725     // At this point, we know the LCS: it's in the reverse of the
69726     // linked-list through .chain of
69727     // candidates[candidates.length - 1].
69728
69729     return candidates[candidates.length - 1];
69730 }
69731
69732
69733
69734
69735
69736
69737
69738
69739
69740
69741
69742 function diff_indices(file1, file2) {
69743     // We apply the LCS to give a simple representation of the
69744     // offsets and lengths of mismatched chunks in the input
69745     // files. This is used by diff3_merge_indices below.
69746
69747     var result = [];
69748     var tail1 = file1.length;
69749     var tail2 = file2.length;
69750
69751     for (var candidate = longest_common_subsequence(file1, file2);
69752          candidate !== null;
69753          candidate = candidate.chain)
69754     {
69755         var mismatchLength1 = tail1 - candidate.file1index - 1;
69756         var mismatchLength2 = tail2 - candidate.file2index - 1;
69757         tail1 = candidate.file1index;
69758         tail2 = candidate.file2index;
69759
69760         if (mismatchLength1 || mismatchLength2) {
69761             result.push({file1: [tail1 + 1, mismatchLength1],
69762                          file2: [tail2 + 1, mismatchLength2]});
69763         }
69764     }
69765
69766     result.reverse();
69767     return result;
69768 }
69769
69770 function diff3_merge_indices (a, o, b) {
69771     // Given three files, A, O, and B, where both A and B are
69772     // independently derived from O, returns a fairly complicated
69773     // internal representation of merge decisions it's taken. The
69774     // interested reader may wish to consult
69775     //
69776     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
69777     // Formal Investigation of Diff3." In Arvind and Prasad,
69778     // editors, Foundations of Software Technology and Theoretical
69779     // Computer Science (FSTTCS), December 2007.
69780     //
69781     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
69782     var i;
69783
69784     var m1 = diff_indices(o, a);
69785     var m2 = diff_indices(o, b);
69786
69787     var hunks = [];
69788     function addHunk(h, side) {
69789         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
69790     }
69791     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
69792     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
69793     hunks.sort();
69794
69795     var result = [];
69796     var commonOffset = 0;
69797     function copyCommon(targetOffset) {
69798         if (targetOffset > commonOffset) {
69799             result.push([1, commonOffset, targetOffset - commonOffset]);
69800             commonOffset = targetOffset;
69801         }
69802     }
69803
69804     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
69805         var firstHunkIndex = hunkIndex;
69806         var hunk = hunks[hunkIndex];
69807         var regionLhs = hunk[0];
69808         var regionRhs = regionLhs + hunk[2];
69809         while (hunkIndex < hunks.length - 1) {
69810             var maybeOverlapping = hunks[hunkIndex + 1];
69811             var maybeLhs = maybeOverlapping[0];
69812             if (maybeLhs > regionRhs) break;
69813             regionRhs = maybeLhs + maybeOverlapping[2];
69814             hunkIndex++;
69815         }
69816
69817         copyCommon(regionLhs);
69818         if (firstHunkIndex === hunkIndex) {
69819     // The "overlap" was only one hunk long, meaning that
69820     // there's no conflict here. Either a and o were the
69821     // same, or b and o were the same.
69822             if (hunk[4] > 0) {
69823                 result.push([hunk[1], hunk[3], hunk[4]]);
69824             }
69825         } else {
69826     // A proper conflict. Determine the extents of the
69827     // regions involved from a, o and b. Effectively merge
69828     // all the hunks on the left into one giant hunk, and
69829     // do the same for the right; then, correct for skew
69830     // in the regions of o that each side changed, and
69831     // report appropriate spans for the three sides.
69832     var regions = {
69833         0: [a.length, -1, o.length, -1],
69834         2: [b.length, -1, o.length, -1]
69835     };
69836             for (i = firstHunkIndex; i <= hunkIndex; i++) {
69837         hunk = hunks[i];
69838                 var side = hunk[1];
69839         var r = regions[side];
69840         var oLhs = hunk[0];
69841         var oRhs = oLhs + hunk[2];
69842                 var abLhs = hunk[3];
69843                 var abRhs = abLhs + hunk[4];
69844         r[0] = Math.min(abLhs, r[0]);
69845         r[1] = Math.max(abRhs, r[1]);
69846         r[2] = Math.min(oLhs, r[2]);
69847         r[3] = Math.max(oRhs, r[3]);
69848             }
69849     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
69850     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
69851     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
69852     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
69853             result.push([-1,
69854              aLhs,      aRhs      - aLhs,
69855              regionLhs, regionRhs - regionLhs,
69856              bLhs,      bRhs      - bLhs]);
69857         }
69858         commonOffset = regionRhs;
69859     }
69860
69861     copyCommon(o.length);
69862     return result;
69863 }
69864
69865 function diff3_merge (a, o, b, excludeFalseConflicts) {
69866     // Applies the output of Diff3.diff3_merge_indices to actually
69867     // construct the merged file; the returned result alternates
69868     // between "ok" and "conflict" blocks.
69869
69870     var result = [];
69871     var files = [a, o, b];
69872     var indices = diff3_merge_indices(a, o, b);
69873
69874     var okLines = [];
69875     function flushOk() {
69876         if (okLines.length) {
69877             result.push({ok: okLines});
69878         }
69879         okLines = [];
69880     }
69881     function pushOk(xs) {
69882         for (var j = 0; j < xs.length; j++) {
69883             okLines.push(xs[j]);
69884         }
69885     }
69886
69887     function isTrueConflict(rec) {
69888         if (rec[2] !== rec[6]) return true;
69889         var aoff = rec[1];
69890         var boff = rec[5];
69891         for (var j = 0; j < rec[2]; j++) {
69892             if (a[j + aoff] !== b[j + boff]) return true;
69893         }
69894         return false;
69895     }
69896
69897     for (var i = 0; i < indices.length; i++) {
69898         var x = indices[i];
69899         var side = x[0];
69900         if (side === -1) {
69901             if (excludeFalseConflicts && !isTrueConflict(x)) {
69902                 pushOk(files[0].slice(x[1], x[1] + x[2]));
69903             } else {
69904                 flushOk();
69905                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
69906                                         aIndex: x[1],
69907                                         o: o.slice(x[3], x[3] + x[4]),
69908                                         oIndex: x[3],
69909                                         b: b.slice(x[5], x[5] + x[6]),
69910                                         bIndex: x[5]}});
69911             }
69912         } else {
69913             pushOk(files[side].slice(x[1], x[1] + x[2]));
69914         }
69915     }
69916
69917     flushOk();
69918     return result;
69919 }
69920
69921 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
69922     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
69923         conflicts = [];
69924
69925
69926     function user(d) {
69927         return lodash.isFunction(formatUser) ? formatUser(d) : d;
69928     }
69929
69930
69931     function mergeLocation(remote, target) {
69932         function pointEqual(a, b) {
69933             var epsilon = 1e-6;
69934             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
69935         }
69936
69937         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
69938             return target;
69939         }
69940         if (option === 'force_remote') {
69941             return target.update({loc: remote.loc});
69942         }
69943
69944         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
69945         return target;
69946     }
69947
69948
69949     function mergeNodes(base, remote, target) {
69950         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
69951             return target;
69952         }
69953         if (option === 'force_remote') {
69954             return target.update({nodes: remote.nodes});
69955         }
69956
69957         var ccount = conflicts.length,
69958             o = base.nodes || [],
69959             a = target.nodes || [],
69960             b = remote.nodes || [],
69961             nodes = [],
69962             hunks = diff3_merge(a, o, b, true);
69963
69964         for (var i = 0; i < hunks.length; i++) {
69965             var hunk = hunks[i];
69966             if (hunk.ok) {
69967                 nodes.push.apply(nodes, hunk.ok);
69968             } else {
69969                 // for all conflicts, we can assume c.a !== c.b
69970                 // because `diff3_merge` called with `true` option to exclude false conflicts..
69971                 var c = hunk.conflict;
69972                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
69973                     nodes.push.apply(nodes, c.b);
69974                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
69975                     nodes.push.apply(nodes, c.a);
69976                 } else {       // changed both locally and remotely
69977                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
69978                     break;
69979                 }
69980             }
69981         }
69982
69983         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
69984     }
69985
69986
69987     function mergeChildren(targetWay, children, updates, graph) {
69988         function isUsed(node, targetWay) {
69989             var parentWays = lodash.map(graph.parentWays(node), 'id');
69990             return node.hasInterestingTags() ||
69991                 lodash.without(parentWays, targetWay.id).length > 0 ||
69992                 graph.parentRelations(node).length > 0;
69993         }
69994
69995         var ccount = conflicts.length;
69996
69997         for (var i = 0; i < children.length; i++) {
69998             var id = children[i],
69999                 node = graph.hasEntity(id);
70000
70001             // remove unused childNodes..
70002             if (targetWay.nodes.indexOf(id) === -1) {
70003                 if (node && !isUsed(node, targetWay)) {
70004                     updates.removeIds.push(id);
70005                 }
70006                 continue;
70007             }
70008
70009             // restore used childNodes..
70010             var local = localGraph.hasEntity(id),
70011                 remote = remoteGraph.hasEntity(id),
70012                 target;
70013
70014             if (option === 'force_remote' && remote && remote.visible) {
70015                 updates.replacements.push(remote);
70016
70017             } else if (option === 'force_local' && local) {
70018                 target = osmEntity$$1(local);
70019                 if (remote) {
70020                     target = target.update({ version: remote.version });
70021                 }
70022                 updates.replacements.push(target);
70023
70024             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
70025                 target = osmEntity$$1(local, { version: remote.version });
70026                 if (remote.visible) {
70027                     target = mergeLocation(remote, target);
70028                 } else {
70029                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
70030                 }
70031
70032                 if (conflicts.length !== ccount) break;
70033                 updates.replacements.push(target);
70034             }
70035         }
70036
70037         return targetWay;
70038     }
70039
70040
70041     function updateChildren(updates, graph) {
70042         for (var i = 0; i < updates.replacements.length; i++) {
70043             graph = graph.replace(updates.replacements[i]);
70044         }
70045         if (updates.removeIds.length) {
70046             graph = actionDeleteMultiple(updates.removeIds)(graph);
70047         }
70048         return graph;
70049     }
70050
70051
70052     function mergeMembers(remote, target) {
70053         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
70054             return target;
70055         }
70056         if (option === 'force_remote') {
70057             return target.update({members: remote.members});
70058         }
70059
70060         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
70061         return target;
70062     }
70063
70064
70065     function mergeTags(base, remote, target) {
70066         function ignoreKey(k) {
70067             return lodash.includes(dataDiscarded, k);
70068         }
70069
70070         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
70071             return target;
70072         }
70073         if (option === 'force_remote') {
70074             return target.update({tags: remote.tags});
70075         }
70076
70077         var ccount = conflicts.length,
70078             o = base.tags || {},
70079             a = target.tags || {},
70080             b = remote.tags || {},
70081             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
70082             tags = lodash.clone(a),
70083             changed = false;
70084
70085         for (var i = 0; i < keys.length; i++) {
70086             var k = keys[i];
70087
70088             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
70089                 if (o[k] !== a[k]) {      // changed locally..
70090                     conflicts.push(t('merge_remote_changes.conflict.tags',
70091                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
70092
70093                 } else {                  // unchanged locally, accept remote change..
70094                     if (b.hasOwnProperty(k)) {
70095                         tags[k] = b[k];
70096                     } else {
70097                         delete tags[k];
70098                     }
70099                     changed = true;
70100                 }
70101             }
70102         }
70103
70104         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
70105     }
70106
70107
70108     //  `graph.base()` is the common ancestor of the two graphs.
70109     //  `localGraph` contains user's edits up to saving
70110     //  `remoteGraph` contains remote edits to modified nodes
70111     //  `graph` must be a descendent of `localGraph` and may include
70112     //      some conflict resolution actions performed on it.
70113     //
70114     //                  --- ... --- `localGraph` -- ... -- `graph`
70115     //                 /
70116     //  `graph.base()` --- ... --- `remoteGraph`
70117     //
70118     var action = function(graph) {
70119         var updates = { replacements: [], removeIds: [] },
70120             base = graph.base().entities[id],
70121             local = localGraph.entity(id),
70122             remote = remoteGraph.entity(id),
70123             target = osmEntity$$1(local, { version: remote.version });
70124
70125         // delete/undelete
70126         if (!remote.visible) {
70127             if (option === 'force_remote') {
70128                 return actionDeleteMultiple([id])(graph);
70129
70130             } else if (option === 'force_local') {
70131                 if (target.type === 'way') {
70132                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
70133                     graph = updateChildren(updates, graph);
70134                 }
70135                 return graph.replace(target);
70136
70137             } else {
70138                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
70139                 return graph;  // do nothing
70140             }
70141         }
70142
70143         // merge
70144         if (target.type === 'node') {
70145             target = mergeLocation(remote, target);
70146
70147         } else if (target.type === 'way') {
70148             // pull in any child nodes that may not be present locally..
70149             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
70150             target = mergeNodes(base, remote, target);
70151             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
70152
70153         } else if (target.type === 'relation') {
70154             target = mergeMembers(remote, target);
70155         }
70156
70157         target = mergeTags(base, remote, target);
70158
70159         if (!conflicts.length) {
70160             graph = updateChildren(updates, graph).replace(target);
70161         }
70162
70163         return graph;
70164     };
70165
70166
70167     action.withOption = function(opt) {
70168         option = opt;
70169         return action;
70170     };
70171
70172
70173     action.conflicts = function() {
70174         return conflicts;
70175     };
70176
70177
70178     return action;
70179 }
70180
70181 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70182 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70183 function actionMove(moveIds, tryDelta, projection, cache) {
70184     var delta = tryDelta;
70185
70186     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
70187     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
70188
70189     function setupCache(graph) {
70190         function canMove(nodeId) {
70191             // Allow movement of any node that is in the selectedIDs list..
70192             if (moveIds.indexOf(nodeId) !== -1) return true;
70193
70194             // Allow movement of a vertex where 2 ways meet..
70195             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
70196             if (parents.length < 3) return true;
70197
70198             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
70199             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
70200             if (!parentsMoving) delete cache.moving[nodeId];
70201
70202             return parentsMoving;
70203         }
70204
70205         function cacheEntities(ids) {
70206             ids.forEach(function(id) {
70207                 if (cache.moving[id]) return;
70208                 cache.moving[id] = true;
70209
70210                 var entity = graph.hasEntity(id);
70211                 if (!entity) return;
70212
70213                 if (entity.type === 'node') {
70214                     cache.nodes.push(id);
70215                     cache.startLoc[id] = entity.loc;
70216                 } else if (entity.type === 'way') {
70217                     cache.ways.push(id);
70218                     cacheEntities(entity.nodes);
70219                 } else {
70220                     cacheEntities(entity.members.map(function(member) {
70221                         return member.id;
70222                     }));
70223                 }
70224             });
70225         }
70226
70227         function cacheIntersections(ids) {
70228             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
70229
70230             ids.forEach(function(id) {
70231                 // consider only intersections with 1 moved and 1 unmoved way.
70232                 var childNodes = graph.childNodes(graph.entity(id));
70233                 childNodes.forEach(function(node) {
70234                     var parents = graph.parentWays(node);
70235                     if (parents.length !== 2) return;
70236
70237                     var moved = graph.entity(id),
70238                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
70239                     if (!unmoved) return;
70240
70241                     // exclude ways that are overly connected..
70242                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
70243
70244                     if (moved.isArea() || unmoved.isArea()) return;
70245
70246                     cache.intersection[node.id] = {
70247                         nodeId: node.id,
70248                         movedId: moved.id,
70249                         unmovedId: unmoved.id,
70250                         movedIsEP: isEndpoint(moved, node.id),
70251                         unmovedIsEP: isEndpoint(unmoved, node.id)
70252                     };
70253                 });
70254             });
70255         }
70256
70257
70258         if (!cache) {
70259             cache = {};
70260         }
70261         if (!cache.ok) {
70262             cache.moving = {};
70263             cache.intersection = {};
70264             cache.replacedVertex = {};
70265             cache.startLoc = {};
70266             cache.nodes = [];
70267             cache.ways = [];
70268
70269             cacheEntities(moveIds);
70270             cacheIntersections(cache.ways);
70271             cache.nodes = lodash.filter(cache.nodes, canMove);
70272
70273             cache.ok = true;
70274         }
70275     }
70276
70277
70278     // Place a vertex where the moved vertex used to be, to preserve way shape..
70279     function replaceMovedVertex(nodeId, wayId, graph, delta) {
70280         var way = graph.entity(wayId),
70281             moved = graph.entity(nodeId),
70282             movedIndex = way.nodes.indexOf(nodeId),
70283             len, prevIndex, nextIndex;
70284
70285         if (way.isClosed()) {
70286             len = way.nodes.length - 1;
70287             prevIndex = (movedIndex + len - 1) % len;
70288             nextIndex = (movedIndex + len + 1) % len;
70289         } else {
70290             len = way.nodes.length;
70291             prevIndex = movedIndex - 1;
70292             nextIndex = movedIndex + 1;
70293         }
70294
70295         var prev = graph.hasEntity(way.nodes[prevIndex]),
70296             next = graph.hasEntity(way.nodes[nextIndex]);
70297
70298         // Don't add orig vertex at endpoint..
70299         if (!prev || !next) return graph;
70300
70301         var key = wayId + '_' + nodeId,
70302             orig = cache.replacedVertex[key];
70303         if (!orig) {
70304             orig = osmNode();
70305             cache.replacedVertex[key] = orig;
70306             cache.startLoc[orig.id] = cache.startLoc[nodeId];
70307         }
70308
70309         var start, end;
70310         if (delta) {
70311             start = projection(cache.startLoc[nodeId]);
70312             end = projection.invert(vecAdd(start, delta));
70313         } else {
70314             end = cache.startLoc[nodeId];
70315         }
70316         orig = orig.move(end);
70317
70318         var angle = Math.abs(geoAngle(orig, prev, projection) -
70319                 geoAngle(orig, next, projection)) * 180 / Math.PI;
70320
70321         // Don't add orig vertex if it would just make a straight line..
70322         if (angle > 175 && angle < 185) return graph;
70323
70324         // Don't add orig vertex if another point is already nearby (within 10m)
70325         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
70326             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
70327
70328         // moving forward or backward along way?
70329         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
70330             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
70331             d1 = geoPathLength(p1),
70332             d2 = geoPathLength(p2),
70333             insertAt = (d1 < d2) ? movedIndex : nextIndex;
70334
70335         // moving around closed loop?
70336         if (way.isClosed() && insertAt === 0) insertAt = len;
70337
70338         way = way.addNode(orig.id, insertAt);
70339         return graph.replace(orig).replace(way);
70340     }
70341
70342
70343     // Reorder nodes around intersections that have moved..
70344     function unZorroIntersection(intersection, graph) {
70345         var vertex = graph.entity(intersection.nodeId),
70346             way1 = graph.entity(intersection.movedId),
70347             way2 = graph.entity(intersection.unmovedId),
70348             isEP1 = intersection.movedIsEP,
70349             isEP2 = intersection.unmovedIsEP;
70350
70351         // don't move the vertex if it is the endpoint of both ways.
70352         if (isEP1 && isEP2) return graph;
70353
70354         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
70355             nodes2 = lodash.without(graph.childNodes(way2), vertex);
70356
70357         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
70358         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
70359
70360         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
70361             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
70362             loc;
70363
70364         // snap vertex to nearest edge (or some point between them)..
70365         if (!isEP1 && !isEP2) {
70366             var epsilon = 1e-4, maxIter = 10;
70367             for (var i = 0; i < maxIter; i++) {
70368                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
70369                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
70370                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
70371                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
70372             }
70373         } else if (!isEP1) {
70374             loc = edge1.loc;
70375         } else {
70376             loc = edge2.loc;
70377         }
70378
70379         graph = graph.replace(vertex.move(loc));
70380
70381         // if zorro happened, reorder nodes..
70382         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
70383             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
70384             graph = graph.replace(way1);
70385         }
70386         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
70387             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
70388             graph = graph.replace(way2);
70389         }
70390
70391         return graph;
70392     }
70393
70394
70395     function cleanupIntersections(graph) {
70396         lodash.each(cache.intersection, function(obj) {
70397             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
70398             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
70399             graph = unZorroIntersection(obj, graph);
70400         });
70401
70402         return graph;
70403     }
70404
70405
70406     // check if moving way endpoint can cross an unmoved way, if so limit delta..
70407     function limitDelta(graph) {
70408         lodash.each(cache.intersection, function(obj) {
70409             // Don't limit movement if this is vertex joins 2 endpoints..
70410             if (obj.movedIsEP && obj.unmovedIsEP) return;
70411             // Don't limit movement if this vertex is not an endpoint anyway..
70412             if (!obj.movedIsEP) return;
70413
70414             var node = graph.entity(obj.nodeId),
70415                 start = projection(node.loc),
70416                 end = vecAdd(start, delta),
70417                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
70418                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
70419                     function(loc) { return vecAdd(projection(loc), delta); }),
70420                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
70421                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
70422                 hits = geoPathIntersections(movedPath, unmovedPath);
70423
70424             for (var i = 0; i < hits.length; i++) {
70425                 if (lodash.isEqual(hits[i], end)) continue;
70426                 var edge = geoChooseEdge(unmovedNodes, end, projection);
70427                 delta = vecSub(projection(edge.loc), start);
70428             }
70429         });
70430     }
70431
70432
70433     var action = function(graph) {
70434         if (delta[0] === 0 && delta[1] === 0) return graph;
70435
70436         setupCache(graph);
70437
70438         if (!lodash.isEmpty(cache.intersection)) {
70439             limitDelta(graph);
70440         }
70441
70442         lodash.each(cache.nodes, function(id) {
70443             var node = graph.entity(id),
70444                 start = projection(node.loc),
70445                 end = vecAdd(start, delta);
70446             graph = graph.replace(node.move(projection.invert(end)));
70447         });
70448
70449         if (!lodash.isEmpty(cache.intersection)) {
70450             graph = cleanupIntersections(graph);
70451         }
70452
70453         return graph;
70454     };
70455
70456
70457     action.delta = function() {
70458         return delta;
70459     };
70460
70461
70462     return action;
70463 }
70464
70465 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70466 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70467 function actionMoveNode(nodeId, loc) {
70468     return function(graph) {
70469         return graph.replace(graph.entity(nodeId).move(loc));
70470     };
70471 }
70472
70473 function actionNoop() {
70474     return function(graph) {
70475         return graph;
70476     };
70477 }
70478
70479 /*
70480  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
70481  */
70482 function actionOrthogonalize(wayId, projection) {
70483     var threshold = 12, // degrees within right or straight to alter
70484         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
70485         upperThreshold = Math.cos(threshold * Math.PI / 180);
70486
70487
70488     var action = function(graph, t) {
70489         if (t === null || !isFinite(t)) t = 1;
70490         t = Math.min(Math.max(+t, 0), 1);
70491
70492         var way = graph.entity(wayId),
70493             nodes = graph.childNodes(way),
70494             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
70495             corner = {i: 0, dotp: 1},
70496             epsilon = 1e-4,
70497             node, loc, score, motions, i, j;
70498
70499         if (points.length === 3) {   // move only one vertex for right triangle
70500             for (i = 0; i < 1000; i++) {
70501                 motions = points.map(calcMotion);
70502                 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
70503                 score = corner.dotp;
70504                 if (score < epsilon) {
70505                     break;
70506                 }
70507             }
70508
70509             node = graph.entity(nodes[corner.i].id);
70510             loc = projection.invert(points[corner.i]);
70511             graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70512
70513         } else {
70514             var best,
70515                 originalPoints = lodash.clone(points);
70516             score = Infinity;
70517
70518             for (i = 0; i < 1000; i++) {
70519                 motions = points.map(calcMotion);
70520                 for (j = 0; j < motions.length; j++) {
70521                     points[j] = addPoints(points[j],motions[j]);
70522                 }
70523                 var newScore = squareness(points);
70524                 if (newScore < score) {
70525                     best = lodash.clone(points);
70526                     score = newScore;
70527                 }
70528                 if (score < epsilon) {
70529                     break;
70530                 }
70531             }
70532
70533             points = best;
70534
70535             for (i = 0; i < points.length; i++) {
70536                 // only move the points that actually moved
70537                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
70538                     loc = projection.invert(points[i]);
70539                     node = graph.entity(nodes[i].id);
70540                     graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70541                 }
70542             }
70543
70544             // remove empty nodes on straight sections
70545             for (i = 0; t === 1 && i < points.length; i++) {
70546                 node = graph.entity(nodes[i].id);
70547
70548                 if (graph.parentWays(node).length > 1 ||
70549                     graph.parentRelations(node).length ||
70550                     node.hasInterestingTags()) {
70551                     continue;
70552                 }
70553
70554                 var dotp = normalizedDotProduct(i, points);
70555                 if (dotp < -1 + epsilon) {
70556                     graph = actionDeleteNode(node.id)(graph);
70557                 }
70558             }
70559         }
70560
70561         return graph;
70562
70563
70564         function calcMotion(b, i, array) {
70565             var a = array[(i - 1 + array.length) % array.length],
70566                 c = array[(i + 1) % array.length],
70567                 p = subtractPoints(a, b),
70568                 q = subtractPoints(c, b),
70569                 scale, dotp;
70570
70571             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
70572             p = normalizePoint(p, 1.0);
70573             q = normalizePoint(q, 1.0);
70574
70575             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
70576
70577             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
70578             if (array.length > 3) {
70579                 if (dotp < -0.707106781186547) {
70580                     dotp += 1.0;
70581                 }
70582             } else if (dotp && Math.abs(dotp) < corner.dotp) {
70583                 corner.i = i;
70584                 corner.dotp = Math.abs(dotp);
70585             }
70586
70587             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
70588         }
70589     };
70590
70591
70592     function squareness(points) {
70593         return points.reduce(function(sum, val, i, array) {
70594             var dotp = normalizedDotProduct(i, array);
70595
70596             dotp = filterDotProduct(dotp);
70597             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
70598         }, 0);
70599     }
70600
70601
70602     function normalizedDotProduct(i, points) {
70603         var a = points[(i - 1 + points.length) % points.length],
70604             b = points[i],
70605             c = points[(i + 1) % points.length],
70606             p = subtractPoints(a, b),
70607             q = subtractPoints(c, b);
70608
70609         p = normalizePoint(p, 1.0);
70610         q = normalizePoint(q, 1.0);
70611
70612         return p[0] * q[0] + p[1] * q[1];
70613     }
70614
70615
70616     function subtractPoints(a, b) {
70617         return [a[0] - b[0], a[1] - b[1]];
70618     }
70619
70620
70621     function addPoints(a, b) {
70622         return [a[0] + b[0], a[1] + b[1]];
70623     }
70624
70625
70626     function normalizePoint(point, scale) {
70627         var vector = [0, 0];
70628         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
70629         if (length !== 0) {
70630             vector[0] = point[0] / length;
70631             vector[1] = point[1] / length;
70632         }
70633
70634         vector[0] *= scale;
70635         vector[1] *= scale;
70636
70637         return vector;
70638     }
70639
70640
70641     function filterDotProduct(dotp) {
70642         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
70643             return dotp;
70644         }
70645
70646         return 0;
70647     }
70648
70649
70650     action.disabled = function(graph) {
70651         var way = graph.entity(wayId),
70652             nodes = graph.childNodes(way),
70653             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
70654
70655         if (squareness(points)) {
70656             return false;
70657         }
70658
70659         return 'not_squarish';
70660     };
70661
70662
70663     action.transitionable = true;
70664
70665
70666     return action;
70667 }
70668
70669 // Split a way at the given node.
70670 //
70671 // Optionally, split only the given ways, if multiple ways share
70672 // the given node.
70673 //
70674 // This is the inverse of `iD.actionJoin`.
70675 //
70676 // For testing convenience, accepts an ID to assign to the new way.
70677 // Normally, this will be undefined and the way will automatically
70678 // be assigned a new ID.
70679 //
70680 // Reference:
70681 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
70682 //
70683 function actionSplit(nodeId, newWayIds) {
70684     var wayIds;
70685
70686     // if the way is closed, we need to search for a partner node
70687     // to split the way at.
70688     //
70689     // The following looks for a node that is both far away from
70690     // the initial node in terms of way segment length and nearby
70691     // in terms of beeline-distance. This assures that areas get
70692     // split on the most "natural" points (independent of the number
70693     // of nodes).
70694     // For example: bone-shaped areas get split across their waist
70695     // line, circles across the diameter.
70696     function splitArea(nodes, idxA, graph) {
70697         var lengths = new Array(nodes.length),
70698             length,
70699             i,
70700             best = 0,
70701             idxB;
70702
70703         function wrap(index) {
70704             return utilWrap(index, nodes.length);
70705         }
70706
70707         function dist(nA, nB) {
70708             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
70709         }
70710
70711         // calculate lengths
70712         length = 0;
70713         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
70714             length += dist(nodes[i], nodes[wrap(i-1)]);
70715             lengths[i] = length;
70716         }
70717
70718         length = 0;
70719         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
70720             length += dist(nodes[i], nodes[wrap(i+1)]);
70721             if (length < lengths[i])
70722                 lengths[i] = length;
70723         }
70724
70725         // determine best opposite node to split
70726         for (i = 0; i < nodes.length; i++) {
70727             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
70728             if (cost > best) {
70729                 idxB = i;
70730                 best = cost;
70731             }
70732         }
70733
70734         return idxB;
70735     }
70736
70737
70738     function split(graph, wayA, newWayId) {
70739         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
70740             nodesA,
70741             nodesB,
70742             isArea = wayA.isArea(),
70743             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
70744
70745         if (wayA.isClosed()) {
70746             var nodes = wayA.nodes.slice(0, -1),
70747                 idxA = lodash.indexOf(nodes, nodeId),
70748                 idxB = splitArea(nodes, idxA, graph);
70749
70750             if (idxB < idxA) {
70751                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
70752                 nodesB = nodes.slice(idxB, idxA + 1);
70753             } else {
70754                 nodesA = nodes.slice(idxA, idxB + 1);
70755                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
70756             }
70757         } else {
70758             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
70759             nodesA = wayA.nodes.slice(0, idx + 1);
70760             nodesB = wayA.nodes.slice(idx);
70761         }
70762
70763         wayA = wayA.update({nodes: nodesA});
70764         wayB = wayB.update({nodes: nodesB});
70765
70766         graph = graph.replace(wayA);
70767         graph = graph.replace(wayB);
70768
70769         graph.parentRelations(wayA).forEach(function(relation) {
70770             if (relation.isRestriction()) {
70771                 var via = relation.memberByRole('via');
70772                 if (via && wayB.contains(via.id)) {
70773                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
70774                     graph = graph.replace(relation);
70775                 }
70776             } else {
70777                 if (relation === isOuter) {
70778                     graph = graph.replace(relation.mergeTags(wayA.tags));
70779                     graph = graph.replace(wayA.update({tags: {}}));
70780                     graph = graph.replace(wayB.update({tags: {}}));
70781                 }
70782
70783                 var member = {
70784                     id: wayB.id,
70785                     type: 'way',
70786                     role: relation.memberById(wayA.id).role
70787                 };
70788
70789                 graph = actionAddMember(relation.id, member)(graph);
70790             }
70791         });
70792
70793         if (!isOuter && isArea) {
70794             var multipolygon = osmRelation({
70795                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
70796                 members: [
70797                     {id: wayA.id, role: 'outer', type: 'way'},
70798                     {id: wayB.id, role: 'outer', type: 'way'}
70799                 ]});
70800
70801             graph = graph.replace(multipolygon);
70802             graph = graph.replace(wayA.update({tags: {}}));
70803             graph = graph.replace(wayB.update({tags: {}}));
70804         }
70805
70806         return graph;
70807     }
70808
70809
70810     var action = function(graph) {
70811         var candidates = action.ways(graph);
70812         for (var i = 0; i < candidates.length; i++) {
70813             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
70814         }
70815         return graph;
70816     };
70817
70818
70819     action.ways = function(graph) {
70820         var node = graph.entity(nodeId),
70821             parents = graph.parentWays(node),
70822             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
70823
70824         return parents.filter(function(parent) {
70825             if (wayIds && wayIds.indexOf(parent.id) === -1)
70826                 return false;
70827
70828             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
70829                 return false;
70830
70831             if (parent.isClosed()) {
70832                 return true;
70833             }
70834
70835             for (var i = 1; i < parent.nodes.length - 1; i++) {
70836                 if (parent.nodes[i] === nodeId) {
70837                     return true;
70838                 }
70839             }
70840
70841             return false;
70842         });
70843     };
70844
70845
70846     action.disabled = function(graph) {
70847         var candidates = action.ways(graph);
70848         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
70849             return 'not_eligible';
70850     };
70851
70852
70853     action.limitWays = function(_) {
70854         if (!arguments.length) return wayIds;
70855         wayIds = _;
70856         return action;
70857     };
70858
70859
70860     return action;
70861 }
70862
70863 // Create a restriction relation for `turn`, which must have the following structure:
70864 //
70865 //     {
70866 //         from: { node: <node ID>, way: <way ID> },
70867 //         via:  { node: <node ID> },
70868 //         to:   { node: <node ID>, way: <way ID> },
70869 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
70870 //     }
70871 //
70872 // This specifies a restriction of type `restriction` when traveling from
70873 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
70874 // (The action does not check that these entities form a valid intersection.)
70875 //
70876 // If `restriction` is not provided, it is automatically determined by
70877 // osmInferRestriction.
70878 //
70879 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
70880 // and `to.node` are used to determine which portion of the split ways become
70881 // members of the restriction.
70882 //
70883 // For testing convenience, accepts an ID to assign to the new relation.
70884 // Normally, this will be undefined and the relation will automatically
70885 // be assigned a new ID.
70886 //
70887 function actionRestrictTurn(turn, projection, restrictionId) {
70888
70889     return function(graph) {
70890         var from = graph.entity(turn.from.way),
70891             via  = graph.entity(turn.via.node),
70892             to   = graph.entity(turn.to.way);
70893
70894         function isClosingNode(way, nodeId) {
70895             return nodeId === way.first() && nodeId === way.last();
70896         }
70897
70898         function split(toOrFrom) {
70899             var newID = toOrFrom.newID || osmWay().id;
70900             graph = actionSplit(via.id, [newID])
70901                 .limitWays([toOrFrom.way])(graph);
70902
70903             var a = graph.entity(newID),
70904                 b = graph.entity(toOrFrom.way);
70905
70906             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
70907                 return [a, b];
70908             } else {
70909                 return [b, a];
70910             }
70911         }
70912
70913         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
70914             if (turn.from.node === turn.to.node) {
70915                 // U-turn
70916                 from = to = split(turn.from)[0];
70917             } else if (turn.from.way === turn.to.way) {
70918                 // Straight-on or circular
70919                 var s = split(turn.from);
70920                 from = s[0];
70921                 to   = s[1];
70922             } else {
70923                 // Other
70924                 from = split(turn.from)[0];
70925             }
70926         }
70927
70928         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
70929             to = split(turn.to)[0];
70930         }
70931
70932         return graph.replace(osmRelation({
70933             id: restrictionId,
70934             tags: {
70935                 type: 'restriction',
70936                 restriction: turn.restriction ||
70937                     osmInferRestriction(
70938                         graph,
70939                         turn.from,
70940                         turn.via,
70941                         turn.to,
70942                         projection)
70943             },
70944             members: [
70945                 {id: from.id, type: 'way',  role: 'from'},
70946                 {id: via.id,  type: 'node', role: 'via'},
70947                 {id: to.id,   type: 'way',  role: 'to'}
70948             ]
70949         }));
70950     };
70951 }
70952
70953 function actionRevert(id) {
70954     var action = function(graph) {
70955         var entity = graph.hasEntity(id),
70956             base = graph.base().entities[id];
70957
70958         if (entity && !base) {    // entity will be removed..
70959             if (entity.type === 'node') {
70960                 graph.parentWays(entity)
70961                     .forEach(function(parent) {
70962                         parent = parent.removeNode(id);
70963                         graph = graph.replace(parent);
70964
70965                         if (parent.isDegenerate()) {
70966                             graph = actionDeleteWay(parent.id)(graph);
70967                         }
70968                     });
70969             }
70970
70971             graph.parentRelations(entity)
70972                 .forEach(function(parent) {
70973                     parent = parent.removeMembersWithID(id);
70974                     graph = graph.replace(parent);
70975
70976                     if (parent.isDegenerate()) {
70977                         graph = actionDeleteRelation(parent.id)(graph);
70978                     }
70979                 });
70980         }
70981
70982         return graph.revert(id);
70983     };
70984
70985     return action;
70986 }
70987
70988 function actionRotate(rotateIds, pivot, angle, projection) {
70989
70990     var action = function(graph) {
70991         return graph.update(function(graph) {
70992             utilGetAllNodes(rotateIds, graph).forEach(function(node) {
70993                 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
70994                 graph = graph.replace(node.move(projection.invert(point)));
70995             });
70996         });
70997     };
70998
70999     return action;
71000 }
71001
71002 /*
71003  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
71004  */
71005 function actionStraighten(wayId, projection) {
71006
71007     function positionAlongWay(n, s, e) {
71008         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
71009                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
71010     }
71011
71012
71013     var action = function(graph, t) {
71014         if (t === null || !isFinite(t)) t = 1;
71015         t = Math.min(Math.max(+t, 0), 1);
71016
71017         var way = graph.entity(wayId),
71018             nodes = graph.childNodes(way),
71019             points = nodes.map(function(n) { return projection(n.loc); }),
71020             startPoint = points[0],
71021             endPoint = points[points.length-1],
71022             toDelete = [],
71023             i;
71024
71025         for (i = 1; i < points.length-1; i++) {
71026             var node = nodes[i],
71027                 point = points[i];
71028
71029             if (t < 1 || graph.parentWays(node).length > 1 ||
71030                 graph.parentRelations(node).length ||
71031                 node.hasInterestingTags()) {
71032
71033                 var u = positionAlongWay(point, startPoint, endPoint),
71034                     p = [
71035                         startPoint[0] + u * (endPoint[0] - startPoint[0]),
71036                         startPoint[1] + u * (endPoint[1] - startPoint[1])
71037                     ],
71038                     loc2 = projection.invert(p);
71039
71040                 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
71041
71042             } else {
71043                 // safe to delete
71044                 if (toDelete.indexOf(node) === -1) {
71045                     toDelete.push(node);
71046                 }
71047             }
71048         }
71049
71050         for (i = 0; i < toDelete.length; i++) {
71051             graph = actionDeleteNode(toDelete[i].id)(graph);
71052         }
71053
71054         return graph;
71055     };
71056
71057
71058     action.disabled = function(graph) {
71059         // check way isn't too bendy
71060         var way = graph.entity(wayId),
71061             nodes = graph.childNodes(way),
71062             points = nodes.map(function(n) { return projection(n.loc); }),
71063             startPoint = points[0],
71064             endPoint = points[points.length-1],
71065             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
71066             i;
71067
71068         if (threshold === 0) {
71069             return 'too_bendy';
71070         }
71071
71072         for (i = 1; i < points.length-1; i++) {
71073             var point = points[i],
71074                 u = positionAlongWay(point, startPoint, endPoint),
71075                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
71076                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
71077                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
71078
71079             // to bendy if point is off by 20% of total start/end distance in projected space
71080             if (isNaN(dist) || dist > threshold) {
71081                 return 'too_bendy';
71082             }
71083         }
71084     };
71085
71086
71087     action.transitionable = true;
71088
71089
71090     return action;
71091 }
71092
71093 // Remove the effects of `turn.restriction` on `turn`, which must have the
71094 // following structure:
71095 //
71096 //     {
71097 //         from: { node: <node ID>, way: <way ID> },
71098 //         via:  { node: <node ID> },
71099 //         to:   { node: <node ID>, way: <way ID> },
71100 //         restriction: <relation ID>
71101 //     }
71102 //
71103 // In the simple case, `restriction` is a reference to a `no_*` restriction
71104 // on the turn itself. In this case, it is simply deleted.
71105 //
71106 // The more complex case is where `restriction` references an `only_*`
71107 // restriction on a different turn in the same intersection. In that case,
71108 // that restriction is also deleted, but at the same time restrictions on
71109 // the turns other than the first two are created.
71110 //
71111 function actionUnrestrictTurn(turn) {
71112     return function(graph) {
71113         return actionDeleteRelation(turn.restriction)(graph);
71114     };
71115 }
71116
71117 /* Reflect the given area around its axis of symmetry */
71118 function actionReflect(reflectIds, projection) {
71119     var useLongAxis = true;
71120
71121
71122     // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
71123     // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
71124     function getSmallestSurroundingRectangle(graph, nodes) {
71125         var points = nodes.map(function(n) { return projection(n.loc); }),
71126             hull = d3polygonHull(points),
71127             centroid = d3polygonCentroid(hull),
71128             minArea = Infinity,
71129             ssrExtent = [],
71130             ssrAngle = 0,
71131             c1 = hull[0];
71132
71133         for (var i = 0; i < hull.length - 1; i++) {
71134             var c2 = hull[i + 1],
71135                 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
71136                 poly = geoRotate(hull, -angle, centroid),
71137                 extent$$1 = poly.reduce(function(extent$$1, point) {
71138                         return extent$$1.extend(geoExtent$$1(point));
71139                     }, geoExtent$$1()),
71140                 area$$1 = extent$$1.area();
71141
71142             if (area$$1 < minArea) {
71143                 minArea = area$$1;
71144                 ssrExtent = extent$$1;
71145                 ssrAngle = angle;
71146             }
71147             c1 = c2;
71148         }
71149
71150         return {
71151             poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
71152             angle: ssrAngle
71153         };
71154     }
71155
71156
71157     var action = function(graph, t) {
71158         if (t === null || !isFinite(t)) t = 1;
71159         t = Math.min(Math.max(+t, 0), 1);
71160
71161         var nodes = utilGetAllNodes(reflectIds, graph),
71162             ssr = getSmallestSurroundingRectangle(graph, nodes);
71163
71164         // Choose line pq = axis of symmetry.
71165         // The shape's surrounding rectangle has 2 axes of symmetry.
71166         // Reflect across the longer axis by default.
71167         var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
71168             q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
71169             p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
71170             q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
71171             p, q;
71172
71173         var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
71174         if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
71175             p = p1;
71176             q = q1;
71177         } else {
71178             p = p2;
71179             q = q2;
71180         }
71181
71182         // reflect c across pq
71183         // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
71184         var dx = q[0] - p[0];
71185         var dy = q[1] - p[1];
71186         var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
71187         var b = 2 * dx * dy / (dx * dx + dy * dy);
71188         for (var i = 0; i < nodes.length; i++) {
71189             var node = nodes[i];
71190             var c = projection(node.loc);
71191             var c2 = [
71192                 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
71193                 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
71194             ];
71195             var loc2 = projection.invert(c2);
71196             node = node.move(geoInterp(node.loc, loc2, t));
71197             graph = graph.replace(node);
71198         }
71199
71200         return graph;
71201     };
71202
71203
71204     action.useLongAxis = function(_) {
71205         if (!arguments.length) return useLongAxis;
71206         useLongAxis = _;
71207         return action;
71208     };
71209
71210
71211     action.transitionable = true;
71212
71213
71214     return action;
71215 }
71216
71217
71218
71219 var index$17 = Object.freeze({
71220         d3combobox: d3combobox,
71221         d3geoTile: d3geoTile,
71222         d3keybinding: d3keybinding
71223 });
71224
71225 /* export some legacy symbols: */
71226 var Connection = services.osm;
71227 var debug = false;
71228
71229
71230
71231
71232 var iD = Object.freeze({
71233         Connection: Connection,
71234         debug: debug,
71235         d3: index$2,
71236         lib: index$17,
71237         Context: coreContext,
71238         setAreaKeys: setAreaKeys,
71239         Difference: coreDifference,
71240         Graph: coreGraph$$1,
71241         History: coreHistory,
71242         Tree: coreTree,
71243         Entity: osmEntity$$1,
71244         Node: osmNode,
71245         Relation: osmRelation,
71246         Way: osmWay,
71247         BackgroundSource: rendererBackgroundSource,
71248         Background: rendererBackground,
71249         Features: rendererFeatures,
71250         Map: rendererMap,
71251         TileLayer: rendererTileLayer,
71252         Detect: utilDetect,
71253         actionAddEntity: actionAddEntity,
71254         actionAddMember: actionAddMember,
71255         actionAddMidpoint: actionAddMidpoint,
71256         actionAddVertex: actionAddVertex,
71257         actionChangeMember: actionChangeMember,
71258         actionChangePreset: actionChangePreset,
71259         actionChangeTags: actionChangeTags,
71260         actionCircularize: actionCircularize,
71261         actionConnect: actionConnect,
71262         actionCopyEntities: actionCopyEntities,
71263         actionDeleteMember: actionDeleteMember,
71264         actionDeleteMultiple: actionDeleteMultiple,
71265         actionDeleteNode: actionDeleteNode,
71266         actionDeleteRelation: actionDeleteRelation,
71267         actionDeleteWay: actionDeleteWay,
71268         actionDeprecateTags: actionDeprecateTags,
71269         actionDiscardTags: actionDiscardTags,
71270         actionDisconnect: actionDisconnect,
71271         actionJoin: actionJoin,
71272         actionMerge: actionMerge,
71273         actionMergePolygon: actionMergePolygon,
71274         actionMergeRemoteChanges: actionMergeRemoteChanges,
71275         actionMove: actionMove,
71276         actionMoveNode: actionMoveNode,
71277         actionNoop: actionNoop,
71278         actionOrthogonalize: actionOrthogonalize,
71279         actionRestrictTurn: actionRestrictTurn,
71280         actionReverse: actionReverse,
71281         actionRevert: actionRevert,
71282         actionRotate: actionRotate,
71283         actionSplit: actionSplit,
71284         actionStraighten: actionStraighten,
71285         actionUnrestrictTurn: actionUnrestrictTurn,
71286         actionReflect: actionReflect,
71287         behaviorAddWay: behaviorAddWay,
71288         behaviorBreathe: behaviorBreathe,
71289         behaviorCopy: behaviorCopy,
71290         behaviorDrag: behaviorDrag,
71291         behaviorDrawWay: behaviorDrawWay,
71292         behaviorDraw: behaviorDraw,
71293         behaviorEdit: behaviorEdit,
71294         behaviorHash: behaviorHash,
71295         behaviorHover: behaviorHover,
71296         behaviorLasso: behaviorLasso,
71297         behaviorOperation: behaviorOperation,
71298         behaviorPaste: behaviorPaste,
71299         behaviorSelect: behaviorSelect,
71300         behaviorTail: behaviorTail,
71301         coreContext: coreContext,
71302         coreDifference: coreDifference,
71303         coreGraph: coreGraph$$1,
71304         coreHistory: coreHistory,
71305         coreTree: coreTree,
71306         dataFeatureIcons: dataFeatureIcons,
71307         data: data,
71308         dataWikipedia: dataWikipedia,
71309         dataSuggestions: dataSuggestions,
71310         dataAddressFormats: dataAddressFormats,
71311         dataDeprecated: dataDeprecated,
71312         dataDiscarded: dataDiscarded,
71313         dataLocales: dataLocales,
71314         dataPhoneFormats: dataPhoneFormats,
71315         dataImperial: dataImperial,
71316         dataDriveLeft: dataDriveLeft,
71317         dataEn: en,
71318         geoAngle: geoAngle,
71319         geoChooseEdge: geoChooseEdge,
71320         geoCross: geoCross,
71321         geoEdgeEqual: geoEdgeEqual,
71322         geoEuclideanDistance: geoEuclideanDistance,
71323         geoExtent: geoExtent$$1,
71324         geoInterp: geoInterp,
71325         geoRawMercator: geoRawMercator,
71326         geoRoundCoords: geoRoundCoords,
71327         geoRotate: geoRotate,
71328         geoLatToMeters: geoLatToMeters,
71329         geoLineIntersection: geoLineIntersection,
71330         geoLonToMeters: geoLonToMeters,
71331         geoMetersToLat: geoMetersToLat,
71332         geoMetersToLon: geoMetersToLon,
71333         geoMetersToOffset: geoMetersToOffset,
71334         geoOffsetToMeters: geoOffsetToMeters,
71335         geoPathIntersections: geoPathIntersections,
71336         geoPathLength: geoPathLength,
71337         geoPointInPolygon: geoPointInPolygon,
71338         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
71339         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
71340         geoSphericalDistance: geoSphericalDistance,
71341         modeAddArea: modeAddArea$$1,
71342         modeAddLine: modeAddLine$$1,
71343         modeAddPoint: modeAddPoint$$1,
71344         modeBrowse: modeBrowse,
71345         modeDragNode: modeDragNode$$1,
71346         modeDrawArea: modeDrawArea,
71347         modeDrawLine: modeDrawLine,
71348         modeMove: modeMove$$1,
71349         modeRotate: modeRotate$$1,
71350         modeSave: modeSave$$1,
71351         modeSelect: modeSelect,
71352         operationCircularize: operationCircularize,
71353         operationContinue: operationContinue,
71354         operationDelete: operationDelete,
71355         operationDisconnect: operationDisconnect,
71356         operationMerge: operationMerge,
71357         operationMove: operationMove,
71358         operationOrthogonalize: operationOrthogonalize,
71359         operationReflectShort: operationReflectShort,
71360         operationReflectLong: operationReflectLong,
71361         operationReverse: operationReverse,
71362         operationRotate: operationRotate,
71363         operationSplit: operationSplit,
71364         operationStraighten: operationStraighten,
71365         osmEntity: osmEntity$$1,
71366         osmNode: osmNode,
71367         osmRelation: osmRelation,
71368         osmWay: osmWay,
71369         osmIntersection: osmIntersection,
71370         osmTurn: osmTurn,
71371         osmInferRestriction: osmInferRestriction,
71372         osmLanes: osmLanes,
71373         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
71374         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
71375         osmJoinWays: osmJoinWays,
71376         osmOneWayTags: osmOneWayTags,
71377         osmPavedTags: osmPavedTags,
71378         osmIsInterestingTag: osmIsInterestingTag,
71379         presetCategory: presetCategory,
71380         presetCollection: presetCollection,
71381         presetField: presetField,
71382         presetPreset: presetPreset,
71383         presetIndex: presetIndex,
71384         rendererBackgroundSource: rendererBackgroundSource,
71385         rendererBackground: rendererBackground,
71386         rendererFeatures: rendererFeatures,
71387         rendererMap: rendererMap,
71388         rendererTileLayer: rendererTileLayer,
71389         services: services,
71390         svgAreas: svgAreas$$1,
71391         svgDebug: svgDebug,
71392         svgDefs: svgDefs,
71393         svgGpx: svgGpx,
71394         svgIcon: svgIcon,
71395         svgLabels: svgLabels,
71396         svgLayers: svgLayers,
71397         svgLines: svgLines$$1,
71398         svgMapillaryImages: svgMapillaryImages,
71399         svgMapillarySigns: svgMapillarySigns,
71400         svgMidpoints: svgMidpoints$$1,
71401         svgOneWaySegments: svgOneWaySegments,
71402         svgOsm: svgOsm,
71403         svgPath: svgPath,
71404         svgPointTransform: svgPointTransform,
71405         svgPoints: svgPoints$$1,
71406         svgRelationMemberTags: svgRelationMemberTags,
71407         svgTagClasses: svgTagClasses,
71408         svgTurns: svgTurns,
71409         svgVertices: svgVertices$$1,
71410         uiFields: uiFields,
71411         uiFieldDefaultcheck: uiFieldCheck,
71412         uiFieldCheck: uiFieldCheck,
71413         uiFieldTypeCombo: uiFieldCombo,
71414         uiFieldMultiCombo: uiFieldCombo,
71415         uiFieldNetworkCombo: uiFieldCombo,
71416         uiFieldCombo: uiFieldCombo,
71417         uiFieldUrl: uiFieldText,
71418         uiFieldNumber: uiFieldText,
71419         uiFieldTel: uiFieldText,
71420         uiFieldEmail: uiFieldText,
71421         uiFieldText: uiFieldText,
71422         uiFieldAccess: uiFieldAccess,
71423         uiFieldAddress: uiFieldAddress,
71424         uiFieldCycleway: uiFieldCycleway,
71425         uiFieldLanes: uiFieldLanes,
71426         uiFieldLocalized: uiFieldLocalized,
71427         uiFieldMaxspeed: uiFieldMaxspeed,
71428         uiFieldRadio: uiFieldRadio,
71429         uiFieldRestrictions: uiFieldRestrictions,
71430         uiFieldTextarea: uiFieldTextarea,
71431         uiFieldWikipedia: uiFieldWikipedia,
71432         uiIntro: uiIntro,
71433         uiInit: uiInit,
71434         uiAccount: uiAccount,
71435         uiAttribution: uiAttribution,
71436         uiBackground: uiBackground,
71437         uiCmd: uiCmd,
71438         uiCommit: uiCommit,
71439         uiConfirm: uiConfirm,
71440         uiConflicts: uiConflicts,
71441         uiContributors: uiContributors,
71442         uiDisclosure: uiDisclosure,
71443         uiEntityEditor: uiEntityEditor,
71444         uiFeatureInfo: uiFeatureInfo,
71445         uiFeatureList: uiFeatureList,
71446         uiFlash: uiFlash,
71447         uiFullScreen: uiFullScreen,
71448         uiGeolocate: uiGeolocate,
71449         uiHelp: uiHelp,
71450         uiInfo: uiInfo,
71451         uiInspector: uiInspector,
71452         uiLasso: uiLasso,
71453         uiLoading: uiLoading,
71454         uiMapData: uiMapData,
71455         uiMapInMap: uiMapInMap,
71456         uiModal: uiModal,
71457         uiModes: uiModes,
71458         uiNotice: uiNotice,
71459         uiPreset: uiPreset,
71460         uiPresetIcon: uiPresetIcon,
71461         uiPresetList: uiPresetList,
71462         uiRadialMenu: uiRadialMenu,
71463         uiRawMemberEditor: uiRawMemberEditor,
71464         uiRawMembershipEditor: uiRawMembershipEditor,
71465         uiRawTagEditor: uiRawTagEditor,
71466         uiRestore: uiRestore,
71467         uiSave: uiSave,
71468         uiScale: uiScale,
71469         uiSelectionList: uiSelectionList,
71470         uiSidebar: uiSidebar,
71471         uiSourceSwitch: uiSourceSwitch,
71472         uiSpinner: uiSpinner,
71473         uiSplash: uiSplash,
71474         uiStatus: uiStatus,
71475         uiSuccess: uiSuccess,
71476         uiTagReference: uiTagReference,
71477         uiToggle: uiToggle,
71478         uiTooltipHtml: uiTooltipHtml,
71479         uiUndoRedo: uiUndoRedo,
71480         uiViewOnOSM: uiViewOnOSM,
71481         uiZoom: uiZoom,
71482         utilAsyncMap: utilAsyncMap,
71483         utilDisplayName: utilDisplayName,
71484         utilDisplayNameForPath: utilDisplayNameForPath,
71485         utilDisplayType: utilDisplayType,
71486         utilEditDistance: utilEditDistance,
71487         utilEntitySelector: utilEntitySelector,
71488         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
71489         utilFastMouse: utilFastMouse,
71490         utilFunctor: utilFunctor,
71491         utilGetAllNodes: utilGetAllNodes,
71492         utilGetPrototypeOf: utilGetPrototypeOf,
71493         utilGetSetValue: utilGetSetValue,
71494         utilNoAuto: utilNoAuto,
71495         utilPrefixCSSProperty: utilPrefixCSSProperty,
71496         utilPrefixDOMProperty: utilPrefixDOMProperty,
71497         utilQsString: utilQsString,
71498         utilRebind: utilRebind,
71499         utilSetTransform: utilSetTransform,
71500         utilSessionMutex: utilSessionMutex,
71501         utilStringQs: utilStringQs,
71502         utilSuggestNames: utilSuggestNames,
71503         utilTagText: utilTagText,
71504         utilTriggerEvent: utilTriggerEvent,
71505         utilWrap: utilWrap,
71506         d3combobox: d3combobox,
71507         d3geoTile: d3geoTile,
71508         d3keybinding: d3keybinding,
71509         validationDeprecatedTag: validationDeprecatedTag,
71510         validationDisconnectedHighway: validationDisconnectedHighway,
71511         validationManyDeletions: validationManyDeletions,
71512         validationMissingTag: validationMissingTag,
71513         validationTagSuggestsArea: validationTagSuggestsArea
71514 });
71515
71516 window.iD = iD;
71517
71518 }());
71519 //# sourceMappingURL=iD.js.map