]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
Add a couple of notes to the vagrant instructions
[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","fi":"+358 40 123 4567","hu":"+36 1 123 45 67","hr":"+385 01 123 4567","si":"+386 31 123 4567","it":"+39 01 123 456","va":"+39 01 123 456","gb":"+44 207 123456","gg":"+44 207 123456","im":"+44 207 123456","je":"+44 207 123456","se":"+46 31 123 4567","no":"+47 22 12 34 56","sj":"+47 22 12 34 56","pl":"+48 42 123 4567","de":"+49 89 1234567","br":"+55 11 0982 1098","ru":"+7 495 1234567","kz":"+7 495 1234567","vn":"+84 1 234 5678","hk":"+852 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":"Save changes to OpenStreetMap, making them visible to other users.","no_changes":"No changes to save.","error":"Errors occurred while trying to save","status_code":"Server returned status code {code}","unknown_error_details":"Please ensure you are connected to the internet.","uploading":"Uploading changes to OpenStreetMap.","unsaved_changes":"You have unsaved changes","conflict":{"header":"Resolve conflicting edits","count":"Conflict {num} of {total}","previous":"< Previous","next":"Next >","keep_local":"Keep mine","keep_remote":"Use theirs","restore":"Restore","delete":"Leave Deleted","download_changes":"Or download your changes.","done":"All conflicts resolved!","help":"Another user changed some of the same map features you changed.\nClick on each 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"},"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/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 service,hospice,infirmary,institution,nursing home,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/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/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":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]]},{"id":"AGRI-black_and_white-2.5m","name":"AGRI black-and-white 2.5m","type":"tms","template":"http://agri.openstreetmap.org/{zoom}/{x}/{y}.png","polygon":[[[112.28778,-28.784589],[112.71488,-31.13894],[114.11263,-34.178287],[113.60788,-37.39012],[117.17992,-37.451794],[119.31538,-37.42096],[121.72262,-36.708394],[123.81925,-35.76893],[125.9547,-34.3066],[127.97368,-33.727398],[130.07031,-33.24166],[130.10913,-33.888704],[131.00214,-34.049705],[131.0798,-34.72257],[132.28342,-35.39],[134.18591,-35.61126],[133.8753,-37.1119],[134.8459,-37.6365],[139.7769,-37.82075],[139.93223,-39.4283],[141.6017,-39.8767],[142.3783,-39.368294],[142.3783,-40.64702],[142.49478,-42.074874],[144.009,-44.060127],[147.23161,-44.03222],[149.05645,-42.534313],[149.52237,-40.99959],[149.9494,-40.852921],[150.8036,-38.09627],[151.81313,-38.12682],[156.20052,-22.667706],[156.20052,-20.10109],[156.62761,-17.417627],[155.26869,-17.19521],[154.14272,-19.51662],[153.5215,-18.34139],[153.05558,-16.5636],[152.78379,-15.256768],[152.27905,-13.4135],[151.3472,-12.391767],[149.48354,-12.05024],[146.9598,-9.992408],[135.9719,-9.992408],[130.3032,-10.33636],[128.09016,-12.164136],[125.91588,-12.315912],[124.3239,-11.860326],[122.03323,-11.974295],[118.26706,-16.9353],[115.93747,-19.11357],[114.0738,-21.11863],[113.49141,-22.596033],[112.28778,-28.784589]]],"terms_text":"AGRI"},{"id":"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":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-7th_Series","name":"NLS - OS 1-inch 7th Series 1955-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/seventh/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-1st_Series","name":"NLS - OS 1:25k 1st Series 1937-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25000/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-4.7157244,54.6796556],[-4.6850662,54.6800268],[-4.6835779,54.6623245],[-4.7148782,54.6615818],[-4.7157244,54.6796556]],[[-3.7085748,58.3371151],[-3.5405937,58.3380684],[-3.5315137,58.1608002],[-3.3608086,58.1622372],[-3.3653486,58.252173],[-3.1610473,58.2536063],[-3.1610473,58.3261509],[-3.0275704,58.3271045],[-3.0366505,58.6139001],[-3.0021463,58.614373],[-3.0030543,58.7036341],[-3.4180129,58.7003322],[-3.4171049,58.6290293],[-3.7240109,58.6266658],[-3.7231029,58.606806],[-4.2361262,58.5992374],[-4.2334022,58.5092347],[-3.88836,58.5144516],[-3.8829119,58.4261327],[-3.7158389,58.4270836],[-3.7085748,58.3371151]],[[-6.46676,49.9943621],[-6.1889102,50.004868],[-6.1789222,49.8967815],[-6.3169391,49.8915171],[-6.312399,49.8200979],[-6.4504159,49.8159968],[-6.46676,49.9943621]],[[-5.6453263,50.2029809],[-5.7801329,50.2014076],[-5.7637888,50.0197267],[-5.3479221,50.0290604],[-5.3388421,49.9414854],[-5.024672,49.9473287],[-5.0355681,50.0383923],[-5.0010639,50.0453901],[-4.9974319,50.1304478],[-4.855783,50.13394],[-4.861231,50.206057],[-4.6546085,50.2140172],[-4.6558926,50.3018616],[-4.5184924,50.3026818],[-4.51464,50.325642],[-4.2488284,50.3264618],[-4.2488284,50.3100631],[-4.10886,50.3141633],[-4.1062917,50.2411267],[-3.9648088,50.2432047],[-3.9640778,50.2254158],[-3.8522287,50.2273626],[-3.8503757,50.1552563],[-3.6921809,50.1572487],[-3.5414602,50.1602198],[-3.5465781,50.3226814],[-3.4068012,50.3241013],[-3.4165761,50.5892711],[-3.2746691,50.5962721],[-3.2749172,50.6106323],[-2.9971742,50.613972],[-2.9896008,50.688537],[-2.7120266,50.690565],[-2.710908,50.6195964],[-2.5695473,50.6157538],[-2.5651019,50.5134083],[-2.4014463,50.513379],[-2.3940583,50.6160348],[-2.2894123,50.6147436],[-2.2876184,50.6008549],[-2.1477855,50.6048506],[-2.1451013,50.5325437],[-1.9335117,50.5347477],[-1.9362139,50.6170445],[-1.8573025,50.6228094],[-1.8554865,50.709139],[-1.6066929,50.709139],[-1.6085089,50.6239615],[-1.4450678,50.6228094],[-1.4432518,50.5317039],[-1.1545059,50.5293951],[-1.1472419,50.6170485],[-1.011041,50.6205051],[-1.011041,50.7056889],[-0.704135,50.7045388],[-0.700503,50.7769401],[-0.5860943,50.7723465],[-0.5879103,50.7907181],[-0.0149586,50.7798108],[-0.0185906,50.7625836],[0.0967261,50.7620093],[0.0921861,50.6913106],[0.3046595,50.6890096],[0.3101075,50.7757917],[0.5511831,50.7726336],[0.5529991,50.8432096],[0.695556,50.8403428],[0.696464,50.8592608],[0.9852099,50.8523824],[0.9906579,50.9417226],[1.0160821,50.9411504],[1.0215301,51.0303204],[1.2812198,51.0240383],[1.2848518,51.0948044],[1.4277848,51.0948044],[1.4386809,51.2882859],[1.4713691,51.2871502],[1.4804492,51.3994534],[1.1590151,51.4073836],[1.1590151,51.3869889],[1.0191822,51.3903886],[1.0228142,51.4798247],[0.8793493,51.4843484],[0.8829813,51.5566675],[1.0264462,51.5544092],[1.0373423,51.7493319],[1.2607117,51.7482076],[1.2661598,51.8279642],[1.3351682,51.8335756],[1.3478803,51.9199021],[1.4840812,51.9199021],[1.4986093,52.0038271],[1.6438902,52.0027092],[1.6656823,52.270221],[1.7310588,52.270221],[1.7528509,52.4465637],[1.8254914,52.4476705],[1.8345714,52.624408],[1.7690346,52.6291402],[1.7741711,52.717904],[1.6996925,52.721793],[1.706113,52.8103687],[1.559724,52.8165777],[1.5648605,52.9034116],[1.4184715,52.9103818],[1.4223238,52.9281894],[1.3439928,52.9289635],[1.3491293,53.0001194],[0.4515789,53.022589],[0.4497629,52.9351139],[0.3789384,52.9351139],[0.3716744,52.846365],[0.2227614,52.8496552],[0.2336575,52.9329248],[0.3062979,52.9351139],[0.308114,53.022589],[0.3807544,53.0236813],[0.3993708,53.2933729],[0.3248922,53.2987454],[0.3274604,53.3853782],[0.2504136,53.38691],[0.2581183,53.4748924],[0.1862079,53.4779494],[0.1913443,53.6548777],[0.1502527,53.6594436],[0.1528209,53.7666003],[0.0012954,53.7734308],[0.0025796,53.8424326],[-0.0282392,53.841675],[-0.0226575,53.9311501],[-0.1406983,53.9322193],[-0.1416063,54.0219323],[-0.1706625,54.0235326],[-0.1679384,54.0949482],[-0.0126694,54.0912206],[-0.0099454,54.1811226],[-0.1615824,54.1837795],[-0.1606744,54.2029038],[-0.2405789,54.2034349],[-0.2378549,54.2936234],[-0.3894919,54.2941533],[-0.3857497,54.3837321],[-0.461638,54.3856364],[-0.4571122,54.4939066],[-0.6105651,54.4965434],[-0.6096571,54.5676704],[-0.7667421,54.569776],[-0.7640181,54.5887213],[-0.9192871,54.5908258],[-0.9148116,54.6608348],[-1.1485204,54.6634343],[-1.1472363,54.7528316],[-1.2268514,54.7532021],[-1.2265398,54.8429879],[-1.2991803,54.8435107],[-1.2991803,54.9333391],[-1.3454886,54.9354258],[-1.3436726,55.0234878],[-1.3772688,55.0255698],[-1.3754528,55.1310877],[-1.4997441,55.1315727],[-1.4969272,55.2928323],[-1.5296721,55.2942946],[-1.5258198,55.6523803],[-1.7659492,55.6545537],[-1.7620968,55.7435626],[-1.9688392,55.7435626],[-1.9698023,55.8334505],[-2.0019051,55.8336308],[-2.0015841,55.9235526],[-2.1604851,55.9240613],[-2.1613931,55.9413549],[-2.3202942,55.9408463],[-2.3212022,56.0145126],[-2.5627317,56.0124824],[-2.5645477,56.1022207],[-2.9658863,56.0991822],[-2.9667943,56.1710304],[-2.4828272,56.1755797],[-2.4882752,56.2856078],[-2.5645477,56.2835918],[-2.5681798,56.3742075],[-2.7261728,56.3732019],[-2.7316208,56.4425301],[-2.6190281,56.4425301],[-2.6153961,56.5317671],[-2.453771,56.5347715],[-2.4534686,56.6420248],[-2.4062523,56.6440218],[-2.3953562,56.7297964],[-2.2936596,56.7337811],[-2.2972916,56.807423],[-2.1629067,56.8113995],[-2.1592747,56.9958425],[-1.9922016,57.0017771],[-2.0067297,57.2737477],[-1.9195612,57.2757112],[-1.9304572,57.3482876],[-1.8106005,57.3443682],[-1.7997044,57.4402728],[-1.6616875,57.4285429],[-1.6689516,57.5398256],[-1.7452241,57.5398256],[-1.7524881,57.6313302],[-1.8287606,57.6332746],[-1.8287606,57.7187255],[-3.1768526,57.7171219],[-3.1794208,57.734264],[-3.5134082,57.7292105],[-3.5129542,57.7112683],[-3.7635638,57.7076303],[-3.7598539,57.635713],[-3.8420372,57.6343382],[-3.8458895,57.6178365],[-3.9794374,57.6157733],[-3.9794374,57.686544],[-3.8150708,57.689976],[-3.817639,57.7968899],[-3.6853753,57.7989429],[-3.6892276,57.8891567],[-3.9383458,57.8877915],[-3.9421981,57.9750592],[-3.6943641,57.9784638],[-3.6969323,58.0695865],[-4.0372226,58.0641528],[-4.0346543,57.9730163],[-4.2003051,57.9702923],[-4.1832772,57.7012869],[-4.518752,57.6951111],[-4.5122925,57.6050682],[-4.6789116,57.6016628],[-4.666022,57.4218334],[-3.6677696,57.4394729],[-3.671282,57.5295384],[-3.3384979,57.5331943],[-3.3330498,57.4438859],[-2.8336466,57.4485275],[-2.8236396,56.9992706],[-2.3305398,57.0006693],[-2.3298977,56.9113932],[-2.6579889,56.9092901],[-2.6559637,56.8198406],[-2.8216747,56.8188467],[-2.8184967,56.7295397],[-3.1449248,56.7265508],[-3.1435628,56.6362749],[-3.4679089,56.6350265],[-3.474265,56.7238108],[-3.8011471,56.7188284],[-3.785711,56.4493026],[-3.946428,56.4457896],[-3.9428873,56.2659777],[-4.423146,56.2588459],[-4.4141572,56.0815506],[-4.8944159,56.0708008],[-4.8791072,55.8896994],[-5.1994158,55.8821374],[-5.1852906,55.7023791],[-5.0273445,55.7067203],[-5.0222081,55.6879046],[-4.897649,55.6907999],[-4.8880181,55.6002822],[-4.7339244,55.6046348],[-4.7275038,55.5342082],[-4.773732,55.5334815],[-4.7685955,55.4447227],[-4.8494947,55.4418092],[-4.8405059,55.3506535],[-4.8700405,55.3513836],[-4.8649041,55.2629462],[-4.9920314,55.2592875],[-4.9907473,55.1691779],[-5.0600894,55.1655105],[-5.0575212,55.0751884],[-5.2141831,55.0722477],[-5.1991766,54.8020337],[-5.0466316,54.8062205],[-5.0502636,54.7244996],[-4.9703591,54.7203043],[-4.9776232,54.6215905],[-4.796022,54.6342056],[-4.796022,54.7307917],[-4.8977186,54.7265971],[-4.9086147,54.8145928],[-4.8069181,54.8166856],[-4.8105501,54.7915648],[-4.6943253,54.7978465],[-4.6761652,54.7244996],[-4.5744686,54.7244996],[-4.5599405,54.6426135],[-4.3093309,54.6384098],[-4.3333262,54.8229889],[-4.2626999,54.8274274],[-4.2549952,54.7348587],[-3.8338058,54.7400481],[-3.836374,54.8141105],[-3.7118149,54.8133706],[-3.7143831,54.8318654],[-3.5346072,54.8355633],[-3.5271039,54.9066228],[-3.4808758,54.9084684],[-3.4776655,54.7457328],[-3.5874573,54.744621],[-3.5836049,54.6546166],[-3.7107322,54.6531308],[-3.6991752,54.4550407],[-3.5746161,54.4572801],[-3.5759002,54.3863042],[-3.539945,54.3855564],[-3.5386609,54.297224],[-3.46033,54.2957252],[-3.4590458,54.2079507],[-3.3807149,54.2102037],[-3.381999,54.1169788],[-3.302878,54.1160656],[-3.300154,54.0276224],[-3.1013007,54.0292224],[-3.093596,53.6062158],[-3.2065981,53.6016441],[-3.2091663,53.4917753],[-3.2451215,53.4887193],[-3.2348486,53.4045934],[-3.5276266,53.3999999],[-3.5343966,53.328481],[-3.6488053,53.3252272],[-3.6527308,53.3057716],[-3.7271873,53.3046865],[-3.7315003,53.3945257],[-3.9108315,53.3912769],[-3.9071995,53.3023804],[-3.9521457,53.3015665],[-3.9566724,53.3912183],[-4.1081979,53.3889209],[-4.1081979,53.4072967],[-4.2622916,53.4065312],[-4.2635757,53.4753707],[-4.638537,53.4677274],[-4.6346847,53.3812621],[-4.7091633,53.3774321],[-4.7001745,53.1954965],[-4.5499332,53.1962658],[-4.5435126,53.1092488],[-4.3919871,53.1100196],[-4.3855666,53.0236002],[-4.6115707,53.0205105],[-4.603866,52.9284932],[-4.7566756,52.9261709],[-4.7476868,52.8370555],[-4.8208813,52.8331768],[-4.8208813,52.7446476],[-4.3701572,52.7539749],[-4.3765778,52.8401583],[-4.2314728,52.8455875],[-4.2237682,52.7586379],[-4.1056297,52.7570836],[-4.1015192,52.6714874],[-4.1487355,52.6703862],[-4.1305754,52.4008596],[-4.1995838,52.3986435],[-4.2050319,52.3110195],[-4.3466808,52.303247],[-4.3484968,52.2365693],[-4.4901457,52.2332328],[-4.4883297,52.2098702],[-4.6572188,52.2098702],[-4.6590348,52.1385939],[-4.7788916,52.13525],[-4.7807076,52.1162967],[-4.9259885,52.1140663],[-4.9187245,52.0392855],[-5.2365265,52.0314653],[-5.2347105,51.9442339],[-5.3473032,51.9408755],[-5.3473032,51.9195995],[-5.4925842,51.9162392],[-5.4853201,51.8265386],[-5.1983903,51.8321501],[-5.1893102,51.7625177],[-5.335825,51.7589528],[-5.3281204,51.6686495],[-5.1836575,51.6730296],[-5.1836575,51.6539134],[-5.0674452,51.6578966],[-5.0603825,51.5677905],[-4.5974594,51.5809588],[-4.60388,51.6726314],[-4.345773,51.6726314],[-4.3355001,51.4962964],[-3.9528341,51.5106841],[-3.9425611,51.5905333],[-3.8809237,51.5953198],[-3.8706508,51.5074872],[-3.7679216,51.4978952],[-3.7550805,51.4242895],[-3.5855774,51.41468],[-3.5778727,51.3329177],[-3.0796364,51.3329177],[-3.0770682,51.2494018],[-3.7216935,51.2381477],[-3.7216935,51.2558315],[-3.8706508,51.2558315],[-3.8680825,51.2365398],[-4.2944084,51.2252825],[-4.289272,51.0496352],[-4.5692089,51.0431767],[-4.5624122,50.9497388],[-4.5905604,50.9520269],[-4.5896524,50.8627065],[-4.6296046,50.8592677],[-4.6226411,50.7691513],[-4.6952816,50.7680028],[-4.6934655,50.6967379],[-4.8342064,50.6938621],[-4.8296664,50.6046231],[-4.9676833,50.6000126],[-4.9685913,50.5821427],[-5.1084242,50.5786832],[-5.1029762,50.4892254],[-5.1311244,50.48807],[-5.1274923,50.4163798],[-5.2664172,50.4117509],[-5.2609692,50.3034214],[-5.5124868,50.2976214],[-5.5061308,50.2256428],[-5.6468717,50.2209953],[-5.6453263,50.2029809]],[[-5.1336607,55.2630226],[-5.1021999,55.2639372],[-5.0999527,55.2458239],[-5.1322161,55.2446343],[-5.1336607,55.2630226]],[[-5.6431878,55.5095745],[-5.4861028,55.5126594],[-5.4715747,55.3348829],[-5.6277517,55.3302345],[-5.6431878,55.5095745]],[[-4.7213517,51.2180246],[-4.5804201,51.2212417],[-4.5746416,51.1306736],[-4.7174993,51.1280545],[-4.7213517,51.2180246]],[[-5.1608796,55.4153626],[-5.0045387,55.4190069],[-5.0184798,55.6153521],[-5.1755648,55.6138137],[-5.1608796,55.4153626]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-25inch-hist","name":"NLS - OS 25-inch (Scotland), 1892-1905","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25_inch/scotland_1/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-9.25,54.43],[-9.25,61.12],[0.22,61.12],[0.22,54.43],[-9.25,54.43]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-6inch-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":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]]},{"id":"OS-New_Popular_Edition-historic","name":"OS New Popular Edition historic","type":"tms","template":"http://ooc.openstreetmap.org/npe/{zoom}/{x}/{y}.png","polygon":[[[-5.8,49.8],[-5.8,55.8],[1.9,55.8],[1.9,49.8],[-5.8,49.8]]]},{"id":"OS-OpenData_Locator","name":"OS OpenData Locator","type":"tms","template":"http://tiles.itoworld.com/os_locator/{zoom}/{x}/{y}.png","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"overlay":true},{"id":"OS-OpenData_StreetView","name":"OS OpenData StreetView","type":"tms","template":"http://os.openstreetmap.org/sv/{zoom}/{x}/{y}.png","scaleExtent":[1,18],"polygon":[[[-5.8292886,50.0229734],[-5.8292886,50.254819],[-5.373356,50.254819],[-5.373356,50.3530588],[-5.1756021,50.3530588],[-5.1756021,50.5925406],[-4.9970743,50.5925406],[-4.9970743,50.6935617],[-4.7965738,50.6935617],[-4.7965738,50.7822112],[-4.6949503,50.7822112],[-4.6949503,50.9607371],[-4.6043131,50.9607371],[-4.6043131,51.0692066],[-4.3792215,51.0692066],[-4.3792215,51.2521782],[-3.9039346,51.2521782],[-3.9039346,51.2916998],[-3.7171671,51.2916998],[-3.7171671,51.2453014],[-3.1486246,51.2453014],[-3.1486246,51.362067],[-3.7446329,51.362067],[-3.7446329,51.4340386],[-3.8297769,51.4340386],[-3.8297769,51.5298246],[-4.0852091,51.5298246],[-4.0852091,51.4939284],[-4.3792215,51.4939284],[-4.3792215,51.5427168],[-5.1444195,51.5427168],[-5.1444195,51.6296003],[-5.7387103,51.6296003],[-5.7387103,51.774037],[-5.5095393,51.774037],[-5.5095393,51.9802596],[-5.198799,51.9802596],[-5.198799,52.0973358],[-4.8880588,52.0973358],[-4.8880588,52.1831557],[-4.4957492,52.1831557],[-4.4957492,52.2925739],[-4.3015365,52.2925739],[-4.3015365,52.3685318],[-4.1811246,52.3685318],[-4.1811246,52.7933685],[-4.4413696,52.7933685],[-4.4413696,52.7369614],[-4.8569847,52.7369614],[-4.8569847,52.9317255],[-4.7288044,52.9317255],[-4.7288044,53.5038599],[-4.1578191,53.5038599],[-4.1578191,53.4113498],[-3.3110518,53.4113498],[-3.3110518,53.5038599],[-3.2333667,53.5038599],[-3.2333667,54.0159169],[-3.3926211,54.0159169],[-3.3926211,54.1980953],[-3.559644,54.1980953],[-3.559644,54.433732],[-3.7188984,54.433732],[-3.7188984,54.721897],[-4.3015365,54.721897],[-4.3015365,54.6140739],[-5.0473132,54.6140739],[-5.0473132,54.7532915],[-5.2298731,54.7532915],[-5.2298731,55.2190799],[-5.6532567,55.2190799],[-5.6532567,55.250088],[-5.8979647,55.250088],[-5.8979647,55.4822462],[-6.5933212,55.4822462],[-6.5933212,56.3013441],[-7.1727691,56.3013441],[-7.1727691,56.5601822],[-6.8171722,56.5601822],[-6.8171722,56.6991713],[-6.5315276,56.6991713],[-6.5315276,56.9066964],[-6.811679,56.9066964],[-6.811679,57.3716613],[-6.8721038,57.3716613],[-6.8721038,57.5518893],[-7.0973235,57.5518893],[-7.0973235,57.2411085],[-7.1742278,57.2411085],[-7.1742278,56.9066964],[-7.3719817,56.9066964],[-7.3719817,56.8075885],[-7.5202972,56.8075885],[-7.5202972,56.7142479],[-7.8306806,56.7142479],[-7.8306806,56.8994605],[-7.6494061,56.8994605],[-7.6494061,57.4739617],[-7.8306806,57.4739617],[-7.8306806,57.7915584],[-7.4736249,57.7915584],[-7.4736249,58.086063],[-7.1879804,58.086063],[-7.1879804,58.367197],[-6.8034589,58.367197],[-6.8034589,58.4155786],[-6.638664,58.4155786],[-6.638664,58.4673277],[-6.5178143,58.4673277],[-6.5178143,58.5625632],[-6.0536224,58.5625632],[-6.0536224,58.1568843],[-6.1470062,58.1568843],[-6.1470062,58.1105865],[-6.2799798,58.1105865],[-6.2799798,57.7122664],[-6.1591302,57.7122664],[-6.1591302,57.6667563],[-5.9339104,57.6667563],[-5.9339104,57.8892524],[-5.80643,57.8892524],[-5.80643,57.9621767],[-5.6141692,57.9621767],[-5.6141692,58.0911236],[-5.490819,58.0911236],[-5.490819,58.3733281],[-5.3199118,58.3733281],[-5.3199118,58.75015],[-3.5719977,58.75015],[-3.5719977,59.2091788],[-3.1944501,59.2091788],[-3.1944501,59.4759216],[-2.243583,59.4759216],[-2.243583,59.1388749],[-2.4611012,59.1388749],[-2.4611012,58.8185938],[-2.7407675,58.8185938],[-2.7407675,58.5804743],[-2.9116746,58.5804743],[-2.9116746,58.1157523],[-3.4865441,58.1157523],[-3.4865441,57.740386],[-1.7153245,57.740386],[-1.7153245,57.2225558],[-1.9794538,57.2225558],[-1.9794538,56.8760742],[-2.1658979,56.8760742],[-2.1658979,56.6333186],[-2.3601106,56.6333186],[-2.3601106,56.0477521],[-1.9794538,56.0477521],[-1.9794538,55.8650949],[-1.4745008,55.8650949],[-1.4745008,55.2499926],[-1.3221997,55.2499926],[-1.3221997,54.8221737],[-1.0550014,54.8221737],[-1.0550014,54.6746628],[-0.6618765,54.6746628],[-0.6618765,54.5527463],[-0.3247617,54.5527463],[-0.3247617,54.2865195],[0.0092841,54.2865195],[0.0092841,53.7938518],[0.2081962,53.7938518],[0.2081962,53.5217726],[0.4163548,53.5217726],[0.4163548,53.0298851],[1.4273388,53.0298851],[1.4273388,52.92021],[1.8333912,52.92021],[1.8333912,52.042488],[1.5235504,52.042488],[1.5235504,51.8261335],[1.2697049,51.8261335],[1.2697049,51.6967453],[1.116651,51.6967453],[1.116651,51.440346],[1.5235504,51.440346],[1.5235504,51.3331831],[1.4507565,51.3331831],[1.4507565,51.0207553],[1.0699883,51.0207553],[1.0699883,50.9008416],[0.7788126,50.9008416],[0.7788126,50.729843],[-0.7255952,50.729843],[-0.7255952,50.7038437],[-1.0074383,50.7038437],[-1.0074383,50.5736307],[-2.3625252,50.5736307],[-2.3625252,50.4846421],[-2.4987805,50.4846421],[-2.4987805,50.5736307],[-3.4096378,50.5736307],[-3.4096378,50.2057837],[-3.6922446,50.2057837],[-3.6922446,50.1347737],[-5.005468,50.1347737],[-5.005468,49.9474456],[-5.2839506,49.9474456],[-5.2839506,50.0229734],[-5.8292886,50.0229734]],[[-6.4580707,49.8673563],[-6.4580707,49.9499935],[-6.3978807,49.9499935],[-6.3978807,50.0053797],[-6.1799606,50.0053797],[-6.1799606,49.9168614],[-6.2540201,49.9168614],[-6.2540201,49.8673563],[-6.4580707,49.8673563]],[[-5.8343165,49.932156],[-5.8343165,49.9754641],[-5.7683254,49.9754641],[-5.7683254,49.932156],[-5.8343165,49.932156]],[[-1.9483797,60.6885737],[-1.9483797,60.3058841],[-1.7543149,60.3058841],[-1.7543149,60.1284428],[-1.5754914,60.1284428],[-1.5754914,59.797917],[-1.0316959,59.797917],[-1.0316959,60.0354518],[-0.6626918,60.0354518],[-0.6626918,60.9103862],[-1.1034395,60.9103862],[-1.1034395,60.8040022],[-1.3506319,60.8040022],[-1.3506319,60.6885737],[-1.9483797,60.6885737]],[[-2.203381,60.1968568],[-2.203381,60.0929443],[-1.9864011,60.0929443],[-1.9864011,60.1968568],[-2.203381,60.1968568]],[[-1.7543149,59.5698289],[-1.7543149,59.4639383],[-1.5373349,59.4639383],[-1.5373349,59.5698289],[-1.7543149,59.5698289]],[[-4.5585981,59.1370518],[-4.5585981,58.9569099],[-4.2867004,58.9569099],[-4.2867004,59.1370518],[-4.5585981,59.1370518]],[[-6.2787732,59.2025744],[-6.2787732,59.0227769],[-5.6650612,59.0227769],[-5.6650612,59.2025744],[-6.2787732,59.2025744]],[[-8.7163482,57.9440556],[-8.7163482,57.7305936],[-8.3592926,57.7305936],[-8.3592926,57.9440556],[-8.7163482,57.9440556]],[[-7.6077005,50.4021026],[-7.6077005,50.2688657],[-7.3907205,50.2688657],[-7.3907205,50.4021026],[-7.6077005,50.4021026]],[[-7.7304303,58.3579902],[-7.7304303,58.248313],[-7.5134503,58.248313],[-7.5134503,58.3579902],[-7.7304303,58.3579902]]]},{"id":"OS-Scottish_Popular-historic","name":"OS Scottish Popular historic","type":"tms","template":"http://ooc.openstreetmap.org/npescotland/tiles/{zoom}/{x}/{y}.jpg","scaleExtent":[6,15],"polygon":[[[-7.8,54.5],[-7.8,61.1],[-1.1,61.1],[-1.1,54.5],[-7.8,54.5]]]},{"id":"Pangasinan_Bulacan_HiRes","name":"Pangasinán/Bulacan (Phillipines HiRes)","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/imagery/philippines/{zoom}/{x}/{y}.png","scaleExtent":[12,19],"polygon":[[[120.336593,15.985768],[120.445995,15.984],[120.446134,15.974459],[120.476464,15.974592],[120.594247,15.946832],[120.598064,16.090795],[120.596537,16.197999],[120.368537,16.218527],[120.347576,16.042308],[120.336593,15.985768]],[[120.8268,15.3658],[121.2684,15.2602],[121.2699,14.7025],[120.695,14.8423],[120.8268,15.3658]]]},{"id":"PNOA-Spain-TMS","name":"PNOA Spain","type":"tms","template":"http://www.ign.es/wmts/pnoa-ma?request=GetTile&service=WMTS&VERSION=1.0.0&Layer=OI.OrthoimageCoverage&Style=default&Format=image/png&TileMatrixSet=GoogleMapsCompatible&TileMatrix={zoom}&TileRow={y}&TileCol={x}","polygon":[[[-17.8846298,28.4460601],[-17.8939535,28.5225529],[-18.0212548,28.7481927],[-18.0224091,28.8038375],[-17.9424017,28.8726124],[-17.8911792,28.8737099],[-17.8903302,28.8515102],[-17.7675902,28.8537764],[-17.7669837,28.8312183],[-17.7412714,28.8319975],[-17.7394926,28.7642235],[-17.7139824,28.7649677],[-17.7129312,28.7303731],[-17.7574427,28.6931782],[-17.7570788,28.6741254],[-17.7457913,28.6743524],[-17.7457266,28.6165627],[-17.7519687,28.5833675],[-17.7622536,28.5591958],[-17.7833086,28.541667],[-17.7831575,28.4936643],[-17.808611,28.4925024],[-17.8060072,28.4468974],[-17.8846298,28.4460601]],[[-18.1661033,27.7851643],[-18.163494,27.6949247],[-18.0889827,27.6963366],[-18.0873398,27.6738724],[-18.0364092,27.6753701],[-18.0350079,27.6302571],[-17.9589987,27.6323976],[-17.8603269,27.7926025],[-17.8630328,27.8368793],[-17.8884015,27.8364947],[-17.8891263,27.8590536],[-17.9906491,27.8567467],[-18.0386803,27.7655831],[-18.1146412,27.7637873],[-18.1154627,27.7863613],[-18.1661033,27.7851643]],[[-17.36038,28.0639801],[-17.3629657,28.1757247],[-17.3375583,28.1763688],[-17.3384577,28.2213012],[-17.1857883,28.2238767],[-17.0820788,28.1351849],[-17.0808422,28.0679977],[-17.1315446,28.0668073],[-17.1563337,28.0214628],[-17.2321063,28.0203711],[-17.2319938,27.9980388],[-17.2576823,27.9978403],[-17.257851,28.0199741],[-17.3086658,28.0192298],[-17.36038,28.0639801]],[[-16.9278171,28.3275779],[-16.9286591,28.3721879],[-16.8776666,28.3729288],[-16.8780707,28.3954191],[-16.5214259,28.4226146],[-16.4457117,28.491135],[-16.4462506,28.535972],[-16.4205859,28.5362679],[-16.4209227,28.5588419],[-16.3443329,28.5597589],[-16.3446023,28.5822095],[-16.1912541,28.5837179],[-16.1916246,28.6068435],[-16.1279344,28.6078193],[-16.1277997,28.5921762],[-16.0995079,28.5925015],[-16.0993395,28.5163822],[-16.1648148,28.5161158],[-16.1647474,28.4938583],[-16.2385755,28.4484704],[-16.2653516,28.4476116],[-16.2658569,28.4030038],[-16.3167484,28.4017594],[-16.3163105,28.380189],[-16.3420763,28.3795075],[-16.3408301,28.2892963],[-16.415837,28.1976134],[-16.415096,28.1311312],[-16.5153297,28.0164796],[-16.6168433,28.01532],[-16.6168096,27.9930469],[-16.7184243,27.9919168],[-16.7190979,28.0371426],[-16.7446952,28.0367859],[-16.7453351,28.0818146],[-16.7706967,28.0816065],[-16.8223966,28.1259036],[-16.8231712,28.1708652],[-16.8487012,28.1707464],[-16.8502842,28.260791],[-16.8756457,28.2605537],[-16.8760836,28.2832162],[-16.9015125,28.2827713],[-16.9023882,28.3279337],[-16.9278171,28.3275779]],[[-15.8537427,27.9008901],[-15.8542032,27.9901812],[-15.828953,27.9906555],[-15.8291065,28.035578],[-15.7782992,28.0363232],[-15.7532793,28.0814298],[-15.7278756,28.0815652],[-15.7282593,28.1718567],[-15.4989741,28.1728039],[-15.4987438,28.1504075],[-15.4497785,28.1507459],[-15.4501622,28.1961425],[-15.3972827,28.1961425],[-15.3964385,28.0383554],[-15.3710348,28.0380167],[-15.3706511,28.0153212],[-15.3457847,28.0153212],[-15.3454777,27.9254406],[-15.3708046,27.9252372],[-15.3705743,27.8352137],[-15.395978,27.8347387],[-15.4209979,27.7879673],[-15.4718052,27.7893932],[-15.471882,27.7666454],[-15.522766,27.7667813],[-15.5477092,27.7216112],[-15.6236132,27.7213395],[-15.6241504,27.741991],[-15.7007451,27.7433495],[-15.801669,27.8110501],[-15.8537427,27.9008901]],[[-14.5215621,28.0467778],[-14.5224358,28.1184131],[-14.4157526,28.1156076],[-14.2168794,28.2278805],[-14.2153651,28.33903],[-14.1641672,28.4528287],[-14.1115132,28.4747955],[-14.0335806,28.7226671],[-13.9565217,28.7449351],[-13.9561722,28.7665857],[-13.8290221,28.7664325],[-13.8289639,28.7879765],[-13.8000741,28.7879255],[-13.8012972,28.7189894],[-13.827566,28.719347],[-13.8278572,28.6517968],[-13.8025786,28.651899],[-13.8033941,28.5384172],[-13.8288474,28.5384684],[-13.8315061,28.3970177],[-13.9158189,28.2241438],[-13.9856445,28.2235696],[-14.0369588,28.1795787],[-14.1387139,28.1799894],[-14.1386556,28.1579103],[-14.2153651,28.1578076],[-14.2147244,28.1118888],[-14.2913173,28.0452356],[-14.3319673,28.0368713],[-14.4457846,28.0469834],[-14.4466583,28.0657961],[-14.4962835,28.0682631],[-14.495934,28.0458525],[-14.5215621,28.0467778]],[[-13.800662,28.8456579],[-13.8009273,28.8231121],[-13.775688,28.8230539],[-13.69729,28.8898184],[-13.69729,28.9127744],[-13.6072498,28.9117991],[-13.4388551,29.0002417],[-13.4374559,29.1351289],[-13.4117005,29.1349931],[-13.4105556,29.2229789],[-13.4592801,29.255586],[-13.4597392,29.2942023],[-13.5091254,29.2945638],[-13.5100581,29.3163453],[-13.5635382,29.3172941],[-13.5640564,29.2713764],[-13.5389228,29.2711956],[-13.5389747,29.2500375],[-13.5661293,29.2501279],[-13.5665956,29.2030039],[-13.5156549,29.2022349],[-13.5156549,29.1820579],[-13.5398038,29.1827819],[-13.5408921,29.137528],[-13.65782,29.1368528],[-13.713222,29.0935079],[-13.7663353,29.0934533],[-13.8502463,29.0165937],[-13.8518224,28.983425],[-13.8524443,28.914861],[-13.9013122,28.89245],[-13.9024005,28.8469779],[-13.800662,28.8456579]],[[1.6479916,38.9990693],[1.7321668,38.9993635],[1.7314703,39.0441733],[1.6489512,39.0431944],[1.6481552,39.1276358],[1.3948608,39.1265691],[1.3954412,39.0864199],[1.2281145,39.0852615],[1.2291095,39.0028958],[1.1448657,39.0018003],[1.1452803,38.8319988],[1.3113632,38.8331615],[1.3121924,38.7906483],[1.3946949,38.7916178],[1.3951924,38.7529597],[1.3112803,38.7519251],[1.3125919,38.6238804],[1.6489036,38.6251112],[1.6480745,38.7111504],[1.58456,38.7101152],[1.5811604,38.7005387],[1.5491544,38.7002798],[1.5197188,38.7092094],[1.50355,38.7253185],[1.4813282,38.9155064],[1.5518906,38.9254411],[1.5667328,38.9566554],[1.6487378,38.9583318],[1.6479916,38.9990693]],[[2.5450749,39.4166673],[2.43933,39.4161122],[2.438714,39.4846853],[2.439022,39.4993424],[2.3122308,39.4993424],[2.3119228,39.5417911],[2.2290722,39.5409994],[2.2283536,39.6260571],[2.3460076,39.6270851],[2.9270445,39.9601558],[3.1456647,39.9600498],[3.1460753,40.0019797],[3.2313899,40.0019797],[3.2312872,39.8329231],[3.1482313,39.8331596],[3.1484366,39.7935717],[3.4814817,39.7931773],[3.4803472,39.5959027],[3.3150618,39.4784606],[3.3146179,39.3785504],[3.0830178,39.2499355],[2.9798608,39.2501482],[2.9790395,39.3334971],[2.7287424,39.3334177],[2.7288451,39.4581361],[2.6456865,39.4577397],[2.6453785,39.4996593],[2.5452802,39.4994216],[2.5450749,39.4166673]],[[3.8120402,40.0434431],[3.729082,40.0437979],[3.7286185,39.9584155],[3.8126633,39.9576011],[3.8122771,39.9164393],[3.9608975,39.9159813],[4.1938142,39.791308],[4.3150279,39.7905799],[4.3159934,39.8329294],[4.3987393,39.8320396],[4.3973664,39.9185834],[4.3158003,39.9193274],[4.3161865,40.0433985],[4.2318959,40.0443594],[4.2324752,40.0847793],[4.1491501,40.086109],[4.1490623,40.1255157],[4.0627981,40.1272166],[4.0624217,40.0849941],[3.8128687,40.085294],[3.8120402,40.0434431]],[[-8.8910646,41.8228891],[-9.1092038,42.5751065],[-9.0365469,42.730656],[-9.0883419,42.7269569],[-9.1466113,42.7750272],[-9.2185488,42.9016271],[-9.2760988,42.8605106],[-9.3099094,42.9311297],[-9.2789763,42.9821991],[-9.3099094,43.0600377],[-9.2523594,43.1041725],[-9.2314975,43.1703151],[-9.1473307,43.210176],[-9.06748,43.1991644],[-9.0336694,43.2426748],[-8.99842,43.2447709],[-8.9998588,43.2955793],[-8.9372732,43.3055265],[-8.92936,43.326986],[-8.8638969,43.3290792],[-8.8761263,43.3740655],[-8.8221732,43.3735426],[-8.785485,43.3191358],[-8.7063538,43.305003],[-8.6099575,43.3296025],[-8.5509688,43.3233227],[-8.5243519,43.3364048],[-8.5250713,43.3646525],[-8.45745,43.3918416],[-8.3610538,43.4111803],[-8.3603344,43.4634161],[-8.3344369,43.5797394],[-8.2776063,43.5708796],[-8.0646713,43.7239184],[-7.9992081,43.7233986],[-7.9171994,43.7826357],[-7.8560525,43.7914643],[-7.83591,43.7374337],[-7.6628443,43.809819],[-7.3188932,43.6782695],[-7.1997467,43.5830817],[-6.2488228,43.6075032],[-6.1229322,43.5790105],[-5.8520425,43.6798953],[-5.6036334,43.5708672],[-5.2855347,43.5619084],[-5.1787525,43.4991591],[-4.9089869,43.4836655],[-4.6156167,43.4192021],[-4.1839917,43.4249168],[-3.8029478,43.5195394],[-3.7400025,43.4869277],[-3.5612827,43.5423572],[-3.1083013,43.3816347],[-2.9385737,43.4624573],[-2.7452417,43.4755094],[-2.3046245,43.3170625],[-1.9854018,43.3563045],[-1.8552841,43.3972545],[-1.769802,43.3964383],[-1.7700492,43.3760501],[-1.7100474,43.3756908],[-1.7113451,43.3312527],[-1.7225915,43.3131806],[-1.6890375,43.3129108],[-1.6881106,43.3341294],[-1.6446695,43.3337248],[-1.6449785,43.3133155],[-1.6029903,43.3129528],[-1.6034352,43.2926624],[-1.5635905,43.2921227],[-1.5630468,43.3133844],[-1.4779905,43.3128355],[-1.3667723,43.2761368],[-1.3568809,43.2381533],[-1.3703692,43.1712972],[-1.4423067,43.0833554],[-1.4198262,43.0603647],[-1.3730668,43.051166],[-1.3640746,43.1115893],[-1.3020285,43.135217],[-1.2354864,43.1332484],[-1.2795481,43.0774443],[-1.1923239,43.0649635],[-1.0061856,43.0077821],[-0.942341,42.9748951],[-0.7562028,42.9821318],[-0.7148387,42.9610774],[-0.6968543,42.9031405],[-0.5511809,42.8220693],[-0.5044215,42.8484456],[-0.4288871,42.8200906],[-0.3164848,42.8655842],[-0.1456332,42.810856],[-0.0314324,42.7124874],[0.1861785,42.7540985],[0.3021777,42.7177729],[0.3642238,42.7428729],[0.4487504,42.7144695],[0.6276949,42.7223973],[0.6411832,42.8576747],[0.7149192,42.882718],[0.9675996,42.8181119],[1.108777,42.7989808],[1.1753192,42.7342872],[1.3632559,42.7415521],[1.4113736,42.7093914],[1.4806054,42.7103407],[1.4813006,42.5010664],[1.6443591,42.5020345],[1.6432777,42.5424539],[1.730407,42.5434214],[1.7316429,42.5011803],[2.0638621,42.5016359],[2.0645572,42.4590247],[2.3969309,42.4599364],[2.3976786,42.4178363],[2.4804823,42.4179732],[2.4809767,42.3759441],[2.6447922,42.3762636],[2.6444832,42.4592447],[2.8113266,42.4596094],[2.8112648,42.5010358],[3.063878,42.5008535],[3.063878,42.4591535],[3.2307832,42.4593359],[3.2304935,42.3764363],[3.3141469,42.3760369],[3.3141243,42.3339864],[3.397855,42.3340435],[3.3973912,42.290094],[3.3138923,42.2908368],[3.3139695,42.2070151],[3.1475896,42.2073012],[3.1475896,42.1260612],[3.2305478,42.1260039],[3.2466753,41.9529359],[3.1945206,41.8558943],[3.060537,41.7647419],[2.7835777,41.6371796],[2.26293,41.4271601],[2.1649151,41.2989297],[1.86008,41.2232228],[1.3763003,41.116273],[1.1793714,41.0464585],[1.0858526,41.048493],[0.758537,40.8195599],[0.9114042,40.733761],[0.8781331,40.6751363],[0.6650182,40.5358666],[0.5580112,40.5502166],[0.433919,40.3757589],[0.2675635,40.1919192],[0.1641534,40.0647234],[0.0751307,40.0144671],[0.010387,39.8952188],[-0.0939224,39.8116904],[-0.1847435,39.6311716],[-0.2908513,39.5036254],[-0.2863552,39.333431],[-0.1856427,39.1774612],[-0.2135185,39.1558487],[-0.1110076,38.9722246],[0.0094878,38.8826835],[0.1218901,38.872183],[0.2342925,38.798636],[0.2558737,38.7264162],[0.0958128,38.6133825],[-0.0022021,38.6070586],[-0.0570544,38.5269073],[-0.2719677,38.4762395],[-0.379874,38.3931234],[-0.3834708,38.3381297],[-0.4509122,38.3310763],[-0.5048654,38.2830943],[-0.4823849,38.1948095],[-0.429331,38.1658287],[-0.4545091,38.148859],[-0.5839966,38.1721913],[-0.6136708,38.1198599],[-0.6370505,37.9612228],[-0.6811123,37.9456238],[-0.7323677,37.8810656],[-0.7215771,37.7830562],[-0.688306,37.7340026],[-0.6641461,37.6231485],[-0.7193941,37.5878413],[-0.9196258,37.5375806],[-1.1107098,37.5164093],[-1.3383246,37.5286671],[-1.4408917,37.3903714],[-1.6766966,37.2765189],[-1.8540816,36.9122889],[-2.0683486,36.6929117],[-2.2158766,36.6619233],[-2.3721861,36.7801753],[-2.6812926,36.6591056],[-2.9201476,36.6675585],[-3.09402,36.712625],[-3.4610839,36.6548788],[-3.7280395,36.6929117],[-4.3743529,36.6633322],[-4.6571151,36.4404171],[-4.9188018,36.4531321],[-5.1699508,36.3513541],[-5.2841094,36.1970201],[-5.2680911,36.1241812],[-5.3524784,36.1224654],[-5.3516094,36.0401413],[-5.4365759,36.0388921],[-5.4353207,36.0034384],[-5.6888562,36.0036518],[-5.6899635,36.0405317],[-5.85506,36.0385595],[-5.8566821,36.1242077],[-5.9384817,36.1221487],[-5.9400265,36.1655625],[-5.9983445,36.1645024],[-6.0357297,36.1780957],[-6.0775178,36.2224132],[-6.1506113,36.2864561],[-6.231541,36.3770075],[-6.3358504,36.5310643],[-6.3214629,36.5816265],[-6.404191,36.6234958],[-6.4743301,36.7489673],[-6.4158808,36.7993866],[-6.490516,36.9173818],[-6.6298949,37.0194012],[-6.8744824,37.1083766],[-7.0426363,37.1850699],[-7.2647434,37.1843535],[-7.3753473,37.1535419],[-7.408316,37.1682196],[-7.4202886,37.2118318],[-7.4249231,37.2350505],[-7.4380543,37.2451969],[-7.4459717,37.3326142],[-7.4480958,37.3909382],[-7.4696271,37.4075829],[-7.4647029,37.4530494],[-7.5019723,37.516411],[-7.5191587,37.5229203],[-7.5219588,37.5723727],[-7.4501271,37.6695835],[-7.4249019,37.7599222],[-7.316662,37.839974],[-7.268329,37.988952],[-7.1536786,38.0155235],[-7.1177098,38.0553626],[-7.0142997,38.0243785],[-6.9963153,38.1075633],[-6.9614706,38.201254],[-7.080617,38.1570753],[-7.3402665,38.4402363],[-7.2638329,38.7380741],[-7.0435243,38.8729667],[-7.0615086,38.907962],[-6.9693387,39.0198308],[-7.0008114,39.0887867],[-7.1536786,39.0957658],[-7.1525545,39.1602899],[-7.2447245,39.1968854],[-7.2559647,39.2813308],[-7.3368944,39.3535074],[-7.3279022,39.4559917],[-7.5144901,39.5886496],[-7.5527069,39.6795427],[-7.0502684,39.6752171],[-6.9951913,39.8195433],[-6.9221297,39.8790868],[-6.886161,40.0229854],[-7.0412762,40.1347927],[-7.0176717,40.266146],[-6.8086034,40.3450071],[-6.8681766,40.4451649],[-6.8535643,40.6066433],[-6.837828,40.8757589],[-6.9536024,41.0370445],[-6.8018592,41.0395879],[-6.7681385,41.138706],[-6.6411239,41.2655616],[-6.5624422,41.2630269],[-6.217367,41.5791017],[-6.3162811,41.644652],[-6.5152332,41.6412921],[-6.5871707,41.6883151],[-6.5478299,41.8559743],[-6.6298836,41.9112057],[-7.1334461,41.9404756],[-7.1682909,41.8718791],[-7.4256922,41.7847727],[-7.9539833,41.8459271],[-8.130455,41.7805819],[-8.2518495,41.9078597],[-8.1293309,42.0348842],[-8.2484774,42.1008034],[-8.3676239,42.0557521],[-8.6070409,42.0340493],[-8.8910646,41.8228891]]],"terms_text":"PNOA","best":true},{"id":"Slovakia-Historic-Maps","name":"Slovakia Historic Maps","type":"tms","template":"http://tms.freemap.sk/historicke/{zoom}/{x}/{y}.png","scaleExtent":[0,12],"polygon":[[[16.8196949,47.4927236],[16.8196949,49.5030322],[22.8388318,49.5030322],[22.8388318,47.4927236],[16.8196949,47.4927236]]]},{"id":"South_Africa-CD_NGI-Aerial","name":"South Africa CD:NGI Aerial","type":"tms","template":"http://{switch:a,b,c}.aerial.openstreetmap.org.za/ngi-aerial/{zoom}/{x}/{y}.jpg","scaleExtent":[1,22],"polygon":[[[17.8396817,-32.7983384],[17.8893509,-32.6972835],[18.00364,-32.6982187],[18.0991679,-32.7485251],[18.2898747,-32.5526645],[18.2930182,-32.0487089],[18.105455,-31.6454966],[17.8529257,-31.3443951],[17.5480046,-30.902171],[17.4044506,-30.6374731],[17.2493704,-30.3991663],[16.9936977,-29.6543552],[16.7987996,-29.19437],[16.5494139,-28.8415949],[16.4498691,-28.691876],[16.4491046,-28.5515766],[16.6002551,-28.4825663],[16.7514057,-28.4486958],[16.7462192,-28.2458973],[16.8855148,-28.04729],[16.9929502,-28.0244005],[17.0529659,-28.0257086],[17.1007562,-28.0338839],[17.2011527,-28.0930546],[17.2026346,-28.2328424],[17.2474611,-28.2338215],[17.2507953,-28.198892],[17.3511919,-28.1975861],[17.3515624,-28.2442655],[17.4015754,-28.2452446],[17.4149122,-28.3489751],[17.4008345,-28.547997],[17.4526999,-28.5489733],[17.4512071,-28.6495106],[17.4983599,-28.6872054],[17.6028204,-28.6830048],[17.6499732,-28.6967928],[17.6525928,-28.7381457],[17.801386,-28.7381457],[17.9994276,-28.7560602],[18.0002748,-28.7956172],[18.1574507,-28.8718055],[18.5063811,-28.8718055],[18.6153564,-28.8295875],[18.9087513,-28.8277516],[19.1046973,-28.9488548],[19.1969071,-28.9378513],[19.243012,-28.8516164],[19.2314858,-28.802963],[19.2587296,-28.7009928],[19.4431493,-28.6973163],[19.5500289,-28.4958332],[19.6967264,-28.4939914],[19.698822,-28.4479358],[19.8507587,-28.4433291],[19.8497109,-28.4027818],[19.9953605,-28.399095],[19.9893671,-24.7497859],[20.2916682,-24.9192346],[20.4724562,-25.1501701],[20.6532441,-25.4529449],[20.733265,-25.6801957],[20.8281046,-25.8963498],[20.8429232,-26.215851],[20.6502804,-26.4840868],[20.6532441,-26.8204869],[21.0889134,-26.846933],[21.6727695,-26.8389998],[21.7765003,-26.6696268],[21.9721069,-26.6431395],[22.2803355,-26.3274702],[22.5707817,-26.1333967],[22.7752795,-25.6775246],[23.0005235,-25.2761948],[23.4658301,-25.2735148],[23.883717,-25.597366],[24.2364017,-25.613402],[24.603905,-25.7896563],[25.110704,-25.7389432],[25.5078447,-25.6855376],[25.6441766,-25.4823781],[25.8419267,-24.7805437],[25.846641,-24.7538456],[26.3928487,-24.6332894],[26.4739066,-24.5653312],[26.5089966,-24.4842437],[26.5861946,-24.4075775],[26.7300635,-24.3014458],[26.8567384,-24.2499463],[26.8574402,-24.1026901],[26.9215471,-23.8990957],[26.931831,-23.8461891],[26.9714827,-23.6994344],[27.0006074,-23.6367644],[27.0578041,-23.6052574],[27.1360547,-23.5203437],[27.3339623,-23.3973792],[27.5144057,-23.3593929],[27.5958145,-23.2085465],[27.8098634,-23.0994957],[27.8828506,-23.0620496],[27.9382928,-22.9496487],[28.0407556,-22.8255118],[28.2056786,-22.6552861],[28.3397223,-22.5639374],[28.4906093,-22.560697],[28.6108769,-22.5400248],[28.828175,-22.4550173],[28.9285324,-22.4232328],[28.9594116,-22.3090081],[29.0162574,-22.208335],[29.2324117,-22.1693453],[29.3531213,-22.1842926],[29.6548952,-22.1186426],[29.7777102,-22.1361956],[29.9292989,-22.1849425],[30.1166795,-22.2830348],[30.2563377,-22.2914767],[30.3033582,-22.3395204],[30.5061784,-22.3057617],[30.8374279,-22.284983],[31.0058599,-22.3077095],[31.1834152,-22.3232913],[31.2930586,-22.3674647],[31.5680579,-23.1903385],[31.5568311,-23.4430809],[31.6931122,-23.6175209],[31.7119696,-23.741136],[31.7774743,-23.8800628],[31.8886337,-23.9481098],[31.9144386,-24.1746736],[31.9948307,-24.3040878],[32.0166656,-24.4405988],[32.0077331,-24.6536578],[32.019643,-24.9140701],[32.035523,-25.0849767],[32.019643,-25.3821442],[31.9928457,-25.4493771],[31.9997931,-25.5165725],[32.0057481,-25.6078978],[32.0057481,-25.6624806],[31.9362735,-25.8403721],[31.9809357,-25.9546537],[31.8687838,-26.0037251],[31.4162062,-25.7277683],[31.3229117,-25.7438611],[31.2504595,-25.8296526],[31.1393001,-25.9162746],[31.1164727,-25.9912361],[30.9656135,-26.2665756],[30.8921689,-26.3279703],[30.8534616,-26.4035568],[30.8226943,-26.4488849],[30.8022583,-26.5240694],[30.8038369,-26.8082089],[30.9020939,-26.7807451],[30.9100338,-26.8489495],[30.9824859,-26.9082627],[30.976531,-27.0029222],[31.0034434,-27.0441587],[31.1543322,-27.1980416],[31.5015607,-27.311117],[31.9700183,-27.311117],[31.9700183,-27.120472],[31.9769658,-27.050664],[32.0002464,-26.7983892],[32.1069826,-26.7984645],[32.3114546,-26.8479493],[32.899986,-26.8516059],[32.886091,-26.9816971],[32.709427,-27.4785436],[32.6240724,-27.7775144],[32.5813951,-28.07479],[32.5387178,-28.2288046],[32.4275584,-28.5021568],[32.3640388,-28.5945699],[32.0702603,-28.8469827],[31.9878832,-28.9069497],[31.7764818,-28.969487],[31.4638459,-29.2859343],[31.359634,-29.3854348],[31.1680825,-29.6307408],[31.064863,-29.7893535],[31.0534493,-29.8470469],[31.0669933,-29.8640319],[31.0455459,-29.9502017],[30.9518556,-30.0033946],[30.8651833,-30.1024093],[30.7244725,-30.392502],[30.3556256,-30.9308873],[30.0972364,-31.2458274],[29.8673136,-31.4304296],[29.7409393,-31.5014699],[29.481312,-31.6978686],[28.8943171,-32.2898903],[28.5497137,-32.5894641],[28.1436499,-32.8320732],[28.0748735,-32.941689],[27.8450942,-33.082869],[27.3757956,-33.3860685],[26.8805407,-33.6458951],[26.5916871,-33.7480756],[26.4527308,-33.7935795],[26.206754,-33.7548943],[26.0077897,-33.7223961],[25.8055494,-33.7524272],[25.7511073,-33.8006512],[25.6529079,-33.8543597],[25.6529079,-33.9469768],[25.7195789,-34.0040115],[25.7202807,-34.0511235],[25.5508915,-34.063151],[25.3504571,-34.0502627],[25.2810609,-34.0020322],[25.0476316,-33.9994588],[24.954724,-34.0043594],[24.9496586,-34.1010363],[24.8770358,-34.1506456],[24.8762914,-34.2005281],[24.8532574,-34.2189562],[24.7645287,-34.2017946],[24.5001356,-34.2003254],[24.3486733,-34.1163824],[24.1988819,-34.1019039],[23.9963377,-34.0514443],[23.8017509,-34.0524332],[23.7493589,-34.0111855],[23.4973536,-34.009014],[23.4155191,-34.0434586],[23.4154284,-34.1140433],[22.9000853,-34.0993009],[22.8412418,-34.0547911],[22.6470321,-34.0502627],[22.6459843,-34.0072768],[22.570016,-34.0064081],[22.5050499,-34.0645866],[22.2519968,-34.0645866],[22.2221334,-34.1014701],[22.1621197,-34.1057019],[22.1712431,-34.1521766],[22.1576913,-34.2180897],[22.0015632,-34.2172232],[21.9496952,-34.3220009],[21.8611528,-34.4007145],[21.5614708,-34.4020114],[21.5468011,-34.3661242],[21.501744,-34.3669892],[21.5006961,-34.4020114],[21.4194886,-34.4465247],[21.1978706,-34.4478208],[21.0988193,-34.3991325],[21.0033746,-34.3753872],[20.893192,-34.3997115],[20.8976647,-34.4854003],[20.7446802,-34.4828092],[20.5042011,-34.486264],[20.2527197,-34.701477],[20.0803502,-34.8361855],[19.9923317,-34.8379056],[19.899074,-34.8275845],[19.8938348,-34.7936018],[19.5972963,-34.7961833],[19.3929677,-34.642015],[19.2877095,-34.6404784],[19.2861377,-34.5986563],[19.3474363,-34.5244458],[19.3285256,-34.4534372],[19.098001,-34.449981],[19.0725583,-34.3802371],[19.0023531,-34.3525593],[18.9520568,-34.3949373],[18.7975006,-34.3936403],[18.7984174,-34.1016376],[18.501748,-34.1015292],[18.4999545,-34.3616945],[18.4477325,-34.3620007],[18.4479944,-34.3522691],[18.3974362,-34.3514041],[18.3971742,-34.3022959],[18.3565705,-34.3005647],[18.3479258,-34.2020436],[18.2972095,-34.1950274],[18.2951139,-33.9937138],[18.3374474,-33.9914079],[18.3476638,-33.8492427],[18.3479258,-33.781555],[18.4124718,-33.7448849],[18.3615477,-33.6501624],[18.2992013,-33.585591],[18.2166839,-33.448872],[18.1389858,-33.3974083],[17.9473472,-33.1602647],[17.8855247,-33.0575732],[17.8485884,-32.9668505],[17.8396817,-32.8507302],[17.8396817,-32.7983384]]],"best":true},{"id":"South-Tyrol-Orthofoto2011","name":"South Tyrol Orthofoto 2011","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2011_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Orthophoto of South Tyrol from 2011","scaleExtent":[0,18],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0"},{"id":"South-Tyrol-Orthofoto2014","name":"South Tyrol Orthofoto 2014","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2014_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Orthophoto of South Tyrol from 2011","scaleExtent":[0,18],"polygon":[[[12.23442,46.84254],[12.24913,46.82785],[12.24913,46.81945],[12.25753,46.81735],[12.26173,46.80686],[12.26594,46.80686],[12.26804,46.79637],[12.26173,46.79427],[12.27014,46.78587],[12.27224,46.76908],[12.28485,46.76698],[12.29745,46.7439],[12.30166,46.7439],[12.30166,46.7376],[12.28695,46.7376],[12.23652,46.72081],[12.18819,46.71451],[12.16298,46.70192],[12.10835,46.69353],[12.08944,46.68303],[12.05792,46.68093],[12.04531,46.67464],[12.03481,46.67464],[12.03061,46.68303],[12.0096,46.68303],[11.98438,46.66834],[11.94866,46.66414],[11.93816,46.65575],[11.90874,46.64525],[11.89193,46.64525],[11.8457,46.62846],[11.82049,46.62636],[11.80998,46.60748],[11.79528,46.60328],[11.78897,46.59069],[11.78057,46.58859],[11.76586,46.55501],[11.75325,46.54871],[11.73855,46.52982],[11.73224,46.52982],[11.72384,46.51513],[11.71543,46.51513],[11.71333,46.50254],[11.70913,46.50254],[11.70913,46.49624],[11.69652,46.48575],[11.69442,46.47735],[11.66711,46.47525],[11.66711,46.44587],[11.6608,46.44587],[11.64399,46.45846],[11.63769,46.45846],[11.63349,46.44587],[11.62508,46.44797],[11.62508,46.43957],[11.61878,46.43957],[11.61458,46.42278],[11.61037,46.42278],[11.61037,46.41649],[11.62508,46.41229],[11.62508,46.3934],[11.61458,46.38291],[11.60617,46.38291],[11.60407,46.37241],[11.58306,46.37241],[11.58306,46.34932],[11.55995,46.32414],[11.53894,46.32834],[11.53894,46.34513],[11.52423,46.34723],[11.50111,46.34723],[11.49901,46.32834],[11.48851,46.33044],[11.49271,46.32204],[11.41917,46.32414],[11.41707,46.25278],[11.35613,46.24858],[11.34773,46.25698],[11.34563,46.26747],[11.34143,46.26747],[11.33722,46.25068],[11.31201,46.24858],[11.30991,46.25278],[11.3015,46.25278],[11.2889,46.24019],[11.2889,46.2234],[11.25108,46.2234],[11.24898,46.2129],[11.16283,46.215],[11.16283,46.24858],[11.12711,46.24858],[11.13131,46.25278],[11.12291,46.25488],[11.12501,46.29895],[11.16283,46.29895],[11.16283,46.36821],[11.16703,46.36821],[11.16703,46.38081],[11.17543,46.3871],[11.17754,46.3997],[11.20485,46.3997],[11.20695,46.42068],[11.19014,46.42068],[11.19014,46.42698],[11.19435,46.42698],[11.19855,46.44167],[11.20485,46.44587],[11.20695,46.47315],[11.19014,46.47525],[11.18804,46.48365],[11.15232,46.47525],[11.08298,46.47525],[11.08088,46.43537],[11.04096,46.42068],[11.01154,46.42068],[10.99894,46.44587],[10.98843,46.44587],[10.98423,46.45217],[10.96952,46.45217],[10.96112,46.48365],[10.95691,46.48365],[10.95481,46.49414],[10.94851,46.49624],[10.94431,46.50673],[10.91069,46.49624],[10.90018,46.49624],[10.89808,46.51093],[10.85606,46.50254],[10.84135,46.54241],[10.86446,46.54661],[10.86236,46.55081],[10.76571,46.54031],[10.72158,46.55081],[10.59762,46.55291],[10.5619,46.54871],[10.53668,46.55291],[10.50096,46.54871],[10.48415,46.55501],[10.46314,46.55501],[10.47155,46.5676],[10.47365,46.59069],[10.47785,46.59069],[10.47785,46.61797],[10.46944,46.62636],[10.44843,46.63476],[10.42532,46.62846],[10.3938,46.63056],[10.3896,46.64525],[10.3812,46.64735],[10.3833,46.66414],[10.3791,46.66834],[10.3791,46.69353],[10.3854,46.72081],[10.3896,46.72081],[10.3938,46.7376],[10.41692,46.75229],[10.41692,46.78587],[10.42112,46.79847],[10.42532,46.79847],[10.42532,46.80686],[10.43373,46.81106],[10.43793,46.79007],[10.44423,46.78377],[10.44843,46.7439],[10.45264,46.7439],[10.45684,46.72711],[10.46104,46.72711],[10.46524,46.71032],[10.46944,46.71032],[10.47365,46.67254],[10.47995,46.67044],[10.48415,46.65575],[10.48836,46.65575],[10.48415,46.62846],[10.48836,46.62846],[10.48836,46.62217],[10.49886,46.62007],[10.52828,46.62427],[10.49886,46.63056],[10.49886,46.64525],[10.50516,46.64316],[10.49886,46.66204],[10.51777,46.65785],[10.58921,46.66204],[10.63123,46.65365],[10.79302,46.65575],[10.79723,46.65155],[10.88127,46.65155],[10.89178,46.65785],[10.9275,46.66414],[10.94431,46.67464],[10.98003,46.67464],[11.00104,46.68303],[11.02415,46.68303],[11.05147,46.69772],[11.12711,46.70822],[11.13971,46.71242],[11.14392,46.71871],[11.17543,46.72081],[11.19855,46.7334],[11.24898,46.7355],[11.25318,46.72291],[11.2952,46.72921],[11.30571,46.70822],[11.31831,46.70822],[11.33722,46.71871],[11.38555,46.72081],[11.43178,46.7376],[11.50952,46.7439],[11.54734,46.75649],[11.56835,46.75649],[11.58306,46.76698],[11.60617,46.76908],[11.61037,46.77538],[11.69862,46.79427],[11.71753,46.79427],[11.72174,46.79007],[11.73855,46.75859],[11.74905,46.75019],[11.76166,46.70192],[11.76586,46.70192],[11.78687,46.71661],[11.8331,46.72291],[11.86041,46.7376],[11.90874,46.7439],[11.92135,46.75229],[11.95286,46.75859],[11.95917,46.76488],[11.99489,46.77538],[12.00749,46.77538],[12.0096,46.77958],[12.03061,46.78168],[12.05792,46.79427],[12.09995,46.79847],[12.13566,46.81316],[12.15878,46.81316],[12.18609,46.82785],[12.21551,46.83205],[12.23442,46.84254]],[[11.97388,46.96637],[11.99489,46.96007],[11.99489,46.95587],[12.0096,46.95797],[12.0117,46.94748],[12.0159,46.94748],[12.0117,46.94118],[12.018,46.93908],[12.02851,46.92229],[12.00749,46.9118],[11.97388,46.9055],[11.95707,46.89501],[11.91714,46.88871],[11.85831,46.86982],[11.8394,46.86982],[11.80158,46.85303],[11.76166,46.84464],[11.74905,46.83415],[11.68181,46.81945],[11.67971,46.81526],[11.6545,46.81106],[11.64399,46.80476],[11.63769,46.80686],[11.63139,46.82155],[11.62508,46.82155],[11.62298,46.83205],[11.61037,46.84464],[11.61668,46.84884],[11.61458,46.85723],[11.61037,46.85723],[11.61668,46.86563],[11.64609,46.86563],[11.68602,46.88242],[11.69022,46.88871],[11.74905,46.89711],[11.75325,46.90341],[11.78057,46.9076],[11.80158,46.9202],[11.8457,46.92649],[11.87722,46.94118],[11.89613,46.94328],[11.92135,46.95797],[11.96757,46.96217],[11.97388,46.96637]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0","best":true},{"id":"South-Tyrol-Topomap","name":"South Tyrol Topomap","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_BASEMAP_TOPO&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Topographical basemap of South Tyrol","scaleExtent":[0,20],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano"},{"id":"Bern-bern2016-tms","name":"Stadt Bern 10cm (2016)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/bern2016/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[7.2943145,46.9237564],[7.2982665,46.9274715],[7.3061586,46.9309487],[7.3043338,46.9362344],[7.3068603,46.9403709],[7.3246431,46.9432765],[7.3284525,46.946409],[7.3414051,46.9460797],[7.3438454,46.9473713],[7.3434554,46.9487937],[7.3513567,46.9485481],[7.3505628,46.950213],[7.3530901,46.9519266],[7.3582028,46.9511773],[7.3685031,46.9566244],[7.3715097,46.9607339],[7.37503,46.959835],[7.3785111,46.9614686],[7.3806232,46.9654741],[7.3832097,46.9663014],[7.3937998,46.9669268],[7.4000528,46.9691779],[7.4082922,46.9686857],[7.4281713,46.9738041],[7.4327053,46.972689],[7.4353602,46.9684345],[7.4378522,46.9684302],[7.4412474,46.9767865],[7.4456893,46.9747939],[7.4483835,46.9756393],[7.4477006,46.9790125],[7.4440468,46.9780682],[7.4412738,46.9798224],[7.4506732,46.9901527],[7.4522112,46.9896803],[7.454649,46.9778182],[7.4680382,46.9758258],[7.4707923,46.969998],[7.4701907,46.9674116],[7.4781618,46.9711823],[7.4845237,46.9701571],[7.4861275,46.9679018],[7.4857945,46.9646828],[7.4784708,46.9629043],[7.4802865,46.9606768],[7.4789304,46.9587841],[7.4797786,46.9566019],[7.4770135,46.9544586],[7.4840504,46.9499938],[7.4833925,46.9451977],[7.4955563,46.9396169],[7.4935119,46.9376594],[7.4908036,46.9387617],[7.4894997,46.9368667],[7.4766667,46.9369496],[7.4781093,46.9362489],[7.4746986,46.9339187],[7.4753537,46.9329898],[7.4691047,46.9292427],[7.4707683,46.9255044],[7.4585674,46.934836],[7.4476373,46.9304297],[7.435418,46.9349668],[7.4338022,46.9331237],[7.4376403,46.9307415],[7.4146941,46.9368183],[7.413844,46.9315682],[7.4070798,46.9303824],[7.408065,46.9256296],[7.4021268,46.9241992],[7.4014835,46.9211927],[7.3875736,46.9304506],[7.3823129,46.927282],[7.3800187,46.9298929],[7.3808694,46.9324085],[7.3748669,46.9314306],[7.3748901,46.9327104],[7.368066,46.9323929],[7.3683058,46.930426],[7.3604074,46.9285884],[7.3605592,46.9272018],[7.338783,46.9245357],[7.3393683,46.9196675],[7.3274574,46.9190326],[7.3269178,46.9235974],[7.324374,46.9251891],[7.3082264,46.9222857],[7.2943145,46.9237564]]],"terms_text":"Orthophoto 2016, Vermessungsamt Stadt Bern ","best":true},{"id":"Uster-2008","name":"Stadt Uster Orthophoto 2008 10cm","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/uster/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.6,47.31],[8.6,47.39],[8.77,47.39],[8.77,47.31],[8.6,47.31]]],"terms_text":"Stadt Uster Vermessung Orthophoto 2008"},{"id":"Zuerich-zh_luftbild2011-tms","name":"Stadt Zürich Luftbild 2011","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_luftbild2011/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4441,47.3141],[8.4441,47.4411],[8.6284,47.4411],[8.6284,47.3141],[8.4441,47.3141]]],"terms_text":"Stadt Zürich Luftbild 2011"},{"id":"Zuerich-city_map","name":"Stadtplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_stadtplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"id":"stamen-terrain-background","name":"Stamen Terrain","type":"tms","template":"http://{switch:a,b,c,d}.tile.stamen.com/terrain-background/{zoom}/{x}/{y}.jpg","scaleExtent":[4,18],"terms_url":"http://maps.stamen.com/#terrain","terms_text":"Map tiles by Stamen Design, under CC BY 3.0"},{"id":"Stevns_Denmark","name":"Stevns (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/stevns/2009/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[12.0913942,55.3491574],[12.0943104,55.3842256],[12.1573875,55.3833103],[12.1587287,55.4013326],[12.1903468,55.400558],[12.1931411,55.4364665],[12.2564251,55.4347995],[12.2547073,55.4168882],[12.3822489,55.4134349],[12.3795942,55.3954143],[12.4109213,55.3946958],[12.409403,55.3766417],[12.4407807,55.375779],[12.4394142,55.3578314],[12.4707413,55.3569971],[12.4629475,55.2672214],[12.4315633,55.2681491],[12.430045,55.2502103],[12.3672011,55.2519673],[12.3656858,55.2340267],[12.2714604,55.2366031],[12.2744467,55.272476],[12.2115654,55.2741475],[12.2130078,55.2920322],[12.1815665,55.2928638],[12.183141,55.3107091],[12.2144897,55.3100981],[12.2159927,55.3279764],[12.1214458,55.3303379],[12.1229489,55.3483291],[12.0913942,55.3491574]]],"terms_text":"Stevns Kommune"},{"id":"Surrey-Air_Survey","name":"Surrey Air Survey","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/surrey/{zoom}/{x}/{y}.png","scaleExtent":[8,19],"polygon":[[[-0.752478,51.0821941],[-0.7595183,51.0856254],[-0.8014342,51.1457917],[-0.8398864,51.1440686],[-0.8357665,51.1802397],[-0.8529549,51.2011266],[-0.8522683,51.2096231],[-0.8495217,51.217903],[-0.8266907,51.2403696],[-0.8120995,51.2469248],[-0.7736474,51.2459577],[-0.7544213,51.2381127],[-0.754078,51.233921],[-0.7446366,51.2333836],[-0.7430693,51.2847178],[-0.751503,51.3069524],[-0.7664376,51.3121032],[-0.7820588,51.3270157],[-0.7815438,51.3388135],[-0.7374268,51.3720456],[-0.7192307,51.3769748],[-0.6795769,51.3847961],[-0.6807786,51.3901523],[-0.6531411,51.3917591],[-0.6301385,51.3905808],[-0.6291085,51.3970074],[-0.6234437,51.3977572],[-0.613144,51.4295552],[-0.6002471,51.4459121],[-0.5867081,51.4445365],[-0.5762368,51.453202],[-0.5626755,51.4523462],[-0.547741,51.4469972],[-0.5372697,51.4448575],[-0.537098,51.4526671],[-0.5439644,51.4545926],[-0.5405312,51.4698865],[-0.5309182,51.4760881],[-0.5091172,51.4744843],[-0.5086022,51.4695657],[-0.4900628,51.4682825],[-0.4526406,51.4606894],[-0.4486924,51.4429316],[-0.4414826,51.4418616],[-0.4418259,51.4369394],[-0.4112702,51.4380095],[-0.4014855,51.4279498],[-0.3807145,51.4262372],[-0.3805428,51.4161749],[-0.3491288,51.4138195],[-0.3274994,51.4037544],[-0.3039818,51.3990424],[-0.3019219,51.3754747],[-0.309475,51.369688],[-0.3111916,51.3529669],[-0.2955704,51.3541462],[-0.2923089,51.3673303],[-0.2850991,51.3680805],[-0.2787476,51.3771891],[-0.2655297,51.3837247],[-0.2411538,51.3847961],[-0.2123147,51.3628288],[-0.2107697,51.3498578],[-0.190857,51.3502867],[-0.1542931,51.3338802],[-0.1496583,51.3057719],[-0.1074296,51.2966491],[-0.0887185,51.3099571],[-0.0878602,51.3220811],[-0.0652009,51.3215448],[-0.0641709,51.3264793],[-0.0519829,51.3263721],[-0.0528412,51.334631],[-0.0330779,51.3430876],[0.0019187,51.3376339],[0.0118751,51.3281956],[0.013935,51.2994398],[0.0202865,51.2994398],[0.0240631,51.3072743],[0.0331611,51.3086694],[0.0455207,51.30545],[0.0523872,51.2877392],[0.0616569,51.2577764],[0.0640602,51.2415518],[0.0462074,51.2126342],[0.0407142,51.2109136],[0.0448341,51.1989753],[0.0494689,51.1997283],[0.0558204,51.1944573],[0.0611419,51.1790713],[0.0623435,51.1542061],[0.0577087,51.1417146],[0.0204582,51.1365447],[-0.0446015,51.1336364],[-0.1566964,51.1352522],[-0.1572114,51.1290043],[-0.2287942,51.1183379],[-0.2473336,51.1183379],[-0.2500802,51.1211394],[-0.299347,51.1137042],[-0.3221779,51.1119799],[-0.3223496,51.1058367],[-0.3596001,51.1019563],[-0.3589135,51.1113333],[-0.3863793,51.1117644],[-0.3869014,51.1062516],[-0.4281001,51.0947174],[-0.4856784,51.0951554],[-0.487135,51.0872266],[-0.5297404,51.0865404],[-0.5302259,51.0789914],[-0.61046,51.076551],[-0.6099745,51.080669],[-0.6577994,51.0792202],[-0.6582849,51.0743394],[-0.6836539,51.0707547],[-0.6997979,51.070831],[-0.7296581,51.0744919],[-0.752478,51.0821941]]]},{"id":"Szeged_2011","name":"Szeged ortophoto 2011","type":"tms","template":"http://e.tile.openstreetmap.hu/szeged-2011-10cm/{zoom}/{x}/{y}.png","scaleExtent":[10,22],"polygon":[[[20.1459914,46.2281144],[20.1332261,46.2290431],[20.1258373,46.2298686],[20.122329,46.2309893],[20.1208484,46.2317537],[20.1189709,46.2335126],[20.1131237,46.2413638],[20.1120293,46.2433005],[20.1115733,46.2449996],[20.1111871,46.247092],[20.1112944,46.2487725],[20.1115948,46.2509686],[20.1122171,46.2528047],[20.1129949,46.2542681],[20.1135421,46.2553549],[20.1147705,46.2567977],[20.1352251,46.2768529],[20.1366386,46.2775055],[20.1378939,46.2780301],[20.1393932,46.2783508],[20.1408818,46.2784583],[20.1611494,46.278159],[20.1621093,46.2781579],[20.1635894,46.277702],[20.1661777,46.2761484],[20.1687795,46.2738569],[20.1696108,46.2714413],[20.1695895,46.2704465],[20.1700871,46.2704418],[20.1739897,46.2643295],[20.1766182,46.2582878],[20.1947983,46.25492],[20.1858719,46.2448077],[20.1846595,46.2453122],[20.1780371,46.2383112],[20.1781766,46.2377101],[20.1795258,46.2370961],[20.1725666,46.2300241],[20.1698349,46.2350404],[20.1687701,46.2362946],[20.1670262,46.2378475],[20.1659431,46.2387342],[20.1654408,46.2389988],[20.1654837,46.2389988],[20.1635177,46.2401383],[20.1602051,46.2412003],[20.1592684,46.241531],[20.1592684,46.2415751],[20.1583504,46.2418505],[20.1549473,46.2422869],[20.1510796,46.2351538],[20.1493804,46.232459],[20.1459914,46.2281144]]],"terms_url":"http://www.geo.u-szeged.hu/","terms_text":"SZTE TFGT - University of Szeged"},{"id":"tnris.org","name":"Texas Orthophoto","type":"tms","template":"https://txgi.tnris.org/login/path/ecology-fiona-poem-romeo/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=texas&STYLE=&FORMAT=image/png&tileMatrixSet=0to20&tileMatrix=0to20:{zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,20],"polygon":[[[-99.9985439,34.5601834],[-95.55654502453,33.99257450647],[-93.89679027134,33.61039304449],[-93.98468089634,32.04103124103],[-93.41613841587,31.02505269211],[-93.74531484297,29.57268254375],[-96.50492070332,28.23158511753],[-97.36942054453,26.95467452634],[-97.04866958924,25.80530249434],[-99.0734177889,26.32559221139],[-100.76599193149,29.02531904433],[-102.3315436893,29.8433892263],[-103.13354564242,28.88112103669],[-104.2887874222,29.28831477845],[-104.7269783935,29.94815782859],[-104.72696778796,30.23535241761],[-106.53450082091,31.78456647831],[-106.75767043939,31.78457253947],[-106.75766067978,32.04385536686],[-106.61848436611,32.04385159755],[-103.11949492759,32.04375683439],[-103.09544343487,36.50045758762],[-103.05798056071,36.54268645422],[-100.00042146824,36.54222227302],[-99.9985439,34.5601834]]],"terms_url":"https://tnris.org/maps-and-data/online-mapping-services/"},{"id":"tf-landscape","name":"Thunderforest Landscape","type":"tms","template":"https://{switch:a,b,c}.tile.thunderforest.com/landscape/{zoom}/{x}/{y}.png","scaleExtent":[0,22],"terms_url":"http://www.thunderforest.com/terms/","terms_text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},{"id":"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":{"office":"coworking"},"name":"Coworking Space","searchable":false},"amenity/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"register_office"},"name":"Register Office","searchable":false},"amenity/swimming_pool":{"icon":"swimming","geometry":["point","vertex","area"],"tags":{"amenity":"swimming_pool"},"name":"Swimming Pool","searchable":false},"amenity/arts_centre":{"icon":"theatre","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"arts_centre"},"name":"Arts Center"},"amenity/atm":{"icon":"bank","fields":["operator","currency_multi","drive_through"],"geometry":["point","vertex"],"terms":["money","cash","machine"],"tags":{"amenity":"atm"},"name":"ATM"},"amenity/bank":{"icon":"bank","fields":["atm","operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"terms":["credit union","check","deposit","fund","investment","repository","reserve","safe","savings","stock","treasury","trust","vault"],"tags":{"amenity":"bank"},"name":"Bank"},"amenity/bar":{"icon":"bar","fields":["operator","address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["dive","beer","bier","booze"],"tags":{"amenity":"bar"},"name":"Bar"},"amenity/bbq":{"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 service","hospice","infirmary","institution","nursing home","sanatorium","sanitarium","sick","surgery","ward"],"tags":{"amenity":"hospital"},"name":"Hospital Grounds"},"amenity/hunting_stand":{"geometry":["point","vertex","area"],"terms":["game","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/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/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"],"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"],"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/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"},"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.languages && navigator.languages.length)
37266         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
37267
37268     // Loaded locale is stored in currentLocale
37269     // return that instead (except in the situation where 'en' might override 'en-US')
37270     var loadedLocale = currentLocale || 'en';
37271     if (loadedLocale !== 'en') {
37272         detected.locale = loadedLocale;
37273     }
37274
37275     // detect text direction
37276     var q = utilStringQs(window.location.hash.substring(1));
37277     var lang = dataLocales[detected.locale];
37278     if ((lang && lang.rtl) || q.hasOwnProperty('rtl')) {
37279         detected.textDirection = 'rtl';
37280     } else {
37281         detected.textDirection = 'ltr';
37282     }
37283     setTextDirection(detected.textDirection);
37284
37285     detected.host = window.location && (window.location.origin + window.location.pathname);
37286
37287     detected.filedrop = (window.FileReader && 'ondrop' in window);
37288
37289     function nav(x) {
37290         return navigator.userAgent.indexOf(x) !== -1;
37291     }
37292
37293     if (nav('Win')) {
37294         detected.os = 'win';
37295         detected.platform = 'Windows';
37296     }
37297     else if (nav('Mac')) {
37298         detected.os = 'mac';
37299         detected.platform = 'Macintosh';
37300     }
37301     else if (nav('X11') || nav('Linux')) {
37302         detected.os = 'linux';
37303         detected.platform = 'Linux';
37304     }
37305     else {
37306         detected.os = 'win';
37307         detected.platform = 'Unknown';
37308     }
37309
37310     return detected;
37311 }
37312
37313 var remove$1 = removeDiacritics;
37314
37315 var replacementList = [
37316   {
37317     base: ' ',
37318     chars: "\u00A0",
37319   }, {
37320     base: '0',
37321     chars: "\u07C0",
37322   }, {
37323     base: 'A',
37324     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",
37325   }, {
37326     base: 'AA',
37327     chars: "\uA732",
37328   }, {
37329     base: 'AE',
37330     chars: "\u00C6\u01FC\u01E2",
37331   }, {
37332     base: 'AO',
37333     chars: "\uA734",
37334   }, {
37335     base: 'AU',
37336     chars: "\uA736",
37337   }, {
37338     base: 'AV',
37339     chars: "\uA738\uA73A",
37340   }, {
37341     base: 'AY',
37342     chars: "\uA73C",
37343   }, {
37344     base: 'B',
37345     chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37346   }, {
37347     base: 'C',
37348     chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37349   }, {
37350     base: 'D',
37351     chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37352   }, {
37353     base: 'Dh',
37354     chars: "\u00D0",
37355   }, {
37356     base: 'DZ',
37357     chars: "\u01F1\u01C4",
37358   }, {
37359     base: 'Dz',
37360     chars: "\u01F2\u01C5",
37361   }, {
37362     base: 'E',
37363     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",
37364   }, {
37365     base: 'F',
37366     chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37367   }, {
37368     base: 'G',
37369     chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37370   }, {
37371     base: 'H',
37372     chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37373   }, {
37374     base: 'I',
37375     chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37376   }, {
37377     base: 'J',
37378     chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37379   }, {
37380     base: 'K',
37381     chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37382   }, {
37383     base: 'L',
37384     chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37385   }, {
37386     base: 'LJ',
37387     chars: "\u01C7",
37388   }, {
37389     base: 'Lj',
37390     chars: "\u01C8",
37391   }, {
37392     base: 'M',
37393     chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37394   }, {
37395     base: 'N',
37396     chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37397   }, {
37398     base: 'NJ',
37399     chars: "\u01CA",
37400   }, {
37401     base: 'Nj',
37402     chars: "\u01CB",
37403   }, {
37404     base: 'O',
37405     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",
37406   }, {
37407     base: 'OE',
37408     chars: "\u0152",
37409   }, {
37410     base: 'OI',
37411     chars: "\u01A2",
37412   }, {
37413     base: 'OO',
37414     chars: "\uA74E",
37415   }, {
37416     base: 'OU',
37417     chars: "\u0222",
37418   }, {
37419     base: 'P',
37420     chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37421   }, {
37422     base: 'Q',
37423     chars: "\u24C6\uFF31\uA756\uA758\u024A",
37424   }, {
37425     base: 'R',
37426     chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37427   }, {
37428     base: 'S',
37429     chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37430   }, {
37431     base: 'T',
37432     chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37433   }, {
37434     base: 'Th',
37435     chars: "\u00DE",
37436   }, {
37437     base: 'TZ',
37438     chars: "\uA728",
37439   }, {
37440     base: 'U',
37441     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",
37442   }, {
37443     base: 'V',
37444     chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37445   }, {
37446     base: 'VY',
37447     chars: "\uA760",
37448   }, {
37449     base: 'W',
37450     chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37451   }, {
37452     base: 'X',
37453     chars: "\u24CD\uFF38\u1E8A\u1E8C",
37454   }, {
37455     base: 'Y',
37456     chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37457   }, {
37458     base: 'Z',
37459     chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37460   }, {
37461     base: 'a',
37462     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",
37463   }, {
37464     base: 'aa',
37465     chars: "\uA733",
37466   }, {
37467     base: 'ae',
37468     chars: "\u00E6\u01FD\u01E3",
37469   }, {
37470     base: 'ao',
37471     chars: "\uA735",
37472   }, {
37473     base: 'au',
37474     chars: "\uA737",
37475   }, {
37476     base: 'av',
37477     chars: "\uA739\uA73B",
37478   }, {
37479     base: 'ay',
37480     chars: "\uA73D",
37481   }, {
37482     base: 'b',
37483     chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37484   }, {
37485     base: 'c',
37486     chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37487   }, {
37488     base: 'd',
37489     chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37490   }, {
37491     base: 'dh',
37492     chars: "\u00F0",
37493   }, {
37494     base: 'dz',
37495     chars: "\u01F3\u01C6",
37496   }, {
37497     base: 'e',
37498     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",
37499   }, {
37500     base: 'f',
37501     chars: "\u24D5\uFF46\u1E1F\u0192",
37502   }, {
37503     base: 'ff',
37504     chars: "\uFB00",
37505   }, {
37506     base: 'fi',
37507     chars: "\uFB01",
37508   }, {
37509     base: 'fl',
37510     chars: "\uFB02",
37511   }, {
37512     base: 'ffi',
37513     chars: "\uFB03",
37514   }, {
37515     base: 'ffl',
37516     chars: "\uFB04",
37517   }, {
37518     base: 'g',
37519     chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37520   }, {
37521     base: 'h',
37522     chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37523   }, {
37524     base: 'hv',
37525     chars: "\u0195",
37526   }, {
37527     base: 'i',
37528     chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37529   }, {
37530     base: 'j',
37531     chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37532   }, {
37533     base: 'k',
37534     chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37535   }, {
37536     base: 'l',
37537     chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37538   }, {
37539     base: 'lj',
37540     chars: "\u01C9",
37541   }, {
37542     base: 'm',
37543     chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37544   }, {
37545     base: 'n',
37546     chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37547   }, {
37548     base: 'nj',
37549     chars: "\u01CC",
37550   }, {
37551     base: 'o',
37552     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",
37553   }, {
37554     base: 'oe',
37555     chars: "\u0153",
37556   }, {
37557     base: 'oi',
37558     chars: "\u01A3",
37559   }, {
37560     base: 'oo',
37561     chars: "\uA74F",
37562   }, {
37563     base: 'ou',
37564     chars: "\u0223",
37565   }, {
37566     base: 'p',
37567     chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37568   }, {
37569     base: 'q',
37570     chars: "\u24E0\uFF51\u024B\uA757\uA759",
37571   }, {
37572     base: 'r',
37573     chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37574   }, {
37575     base: 's',
37576     chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37577   }, {
37578     base: 'ss',
37579     chars: "\xDF",
37580   }, {
37581     base: 't',
37582     chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37583   }, {
37584     base: 'th',
37585     chars: "\u00FE",
37586   }, {
37587     base: 'tz',
37588     chars: "\uA729",
37589   }, {
37590     base: 'u',
37591     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",
37592   }, {
37593     base: 'v',
37594     chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37595   }, {
37596     base: 'vy',
37597     chars: "\uA761",
37598   }, {
37599     base: 'w',
37600     chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37601   }, {
37602     base: 'x',
37603     chars: "\u24E7\uFF58\u1E8B\u1E8D",
37604   }, {
37605     base: 'y',
37606     chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37607   }, {
37608     base: 'z',
37609     chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37610   }
37611 ];
37612
37613 var diacriticsMap = {};
37614 for (var i = 0; i < replacementList.length; i += 1) {
37615   var chars = replacementList[i].chars;
37616   for (var j = 0; j < chars.length; j += 1) {
37617     diacriticsMap[chars[j]] = replacementList[i].base;
37618   }
37619 }
37620
37621 function removeDiacritics(str) {
37622   return str.replace(/[^\u0000-\u007e]/g, function(c) {
37623     return diacriticsMap[c] || c;
37624   });
37625 }
37626
37627 // see https://github.com/openstreetmap/iD/pull/3707
37628 // https://gist.github.com/mapmeld/556b09ddec07a2044c76e1ef45f01c60
37629
37630 var chars$1 = {
37631     // madda above alef
37632     1570: { initial: 'آ‎', isolated: 'ﺁ', medial: 'ﺁ', final: 'ﺂ' },
37633
37634     // hamza above and below alef
37635     1571: { initial: 'أ', isolated: 'ﺃ', medial: '', final: 'ﺄ' },
37636     // 1572 is ؤ
37637     1573: { initial: 'إ', isolated: 'ﺇ', medial: '', final: 'ﺈ' },
37638     // 1574 is ئ
37639     1575: { initial: 'ا', isolated: 'ا', medial: '', final: 'ﺎ' },
37640     1576: { initial: 'ﺑ', isolated: 'ﺏ', medial: 'ﺒ', final: 'ﺐ' },
37641
37642     // 1577 ة
37643     1577: { initial: '', isolated: 'ة', medial: '', final: 'ﺔ' },
37644
37645     1578: { initial: 'ﺗ', isolated: 'ﺕ', medial: 'ﺘ', final: 'ﺖ' },
37646     1579: { initial: 'ﺛ', isolated: 'ﺙ', medial: 'ﺜ', final: 'ﺚ' },
37647     1580: { initial: 'ﺟ', isolated: 'ﺝ', medial: 'ﺠ', final: 'ﺞ' },
37648     1581: { initial: 'ﺣ', isolated: 'ﺡ', medial: 'ﺤ', final: 'ﺢ' },
37649     1582: { initial: 'ﺧ', isolated: 'ﺥ', medial: 'ﺨ', final: 'ﺦ' },
37650     1583: { initial: 'ﺩ', isolated: 'ﺩ', medial: '', final: 'ﺪ' },
37651     1584: { initial: 'ﺫ', isolated: 'ﺫ', medial: '', final: 'ﺬ' },
37652     1585: { initial: 'ﺭ', isolated: 'ﺭ', medial: '', final: 'ﺮ' },
37653     1586: { initial: 'ﺯ', isolated: 'ﺯ', medial: '', final: 'ﺰ' },
37654     1688: { initial: 'ﮊ', isolated: 'ﮊ', medial: '', final: 'ﮋ' },
37655     1587: { initial: 'ﺳ', isolated: 'ﺱ', medial: 'ﺴ', final: 'ﺲ' },
37656     1588: { initial: 'ﺷ', isolated: 'ﺵ', medial: 'ﺸ', final: 'ﺶ' },
37657     1589: { initial: 'ﺻ', isolated: 'ﺹ', medial: 'ﺼ', final: 'ﺺ' },
37658     1590: { initial: 'ﺿ', isolated: 'ﺽ', medial: 'ﻀ', final: 'ﺾ' },
37659     1591: { initial: 'ﻃ', isolated: 'ﻁ', medial: 'ﻄ', final: 'ﻂ' },
37660     1592: { initial: 'ﻇ', isolated: 'ﻅ', medial: 'ﻈ', final: 'ﻆ' },
37661     1593: { initial: 'ﻋ', isolated: 'ﻉ', medial: 'ﻌ', final: 'ﻊ' },
37662     1594: { initial: 'ﻏ', isolated: 'ﻍ', medial: 'ﻐ', final: 'ﻎ' },
37663
37664     // 1595 ػ - may be very rare
37665
37666     1601: { initial: 'ﻓ', isolated: 'ﻑ', medial: 'ﻔ', final: 'ﻒ' },
37667     1602: { initial: 'ﻗ', isolated: 'ﻕ', medial: 'ﻘ', final: 'ﻖ' },
37668     1604: { initial: 'ﻟ', isolated: 'ﻝ', medial: 'ﻠ', final: 'ﻞ' },
37669     1605: { initial: 'ﻣ', isolated: 'ﻡ', medial: 'ﻤ', final: 'ﻢ' },
37670     1606: { initial: 'ﻧ', isolated: 'ﻥ', medial: 'ﻨ', final: 'ﻦ' },
37671     1607: { initial: 'ﻫ', isolated: 'ﻩ', medial: 'ﻬ', final: 'ﻪ' },
37672     1608: { initial: 'ﻭ', isolated: 'ﻭ', medial: '', final: 'ﻮ' },
37673
37674     // 1609 ى
37675     1609: { initial: 'ﯨ', isolated: 'ﻯ', medial: 'ﯩ', final: 'ﻰ' },
37676     // 1610 ي
37677     1610: { initial: 'ﻳ', isolated: 'ﻱ', medial: 'ﻴ', final: 'ﻲ' },
37678
37679     // short vowel sounds / tashkil markings
37680
37681     1662: { initial: 'ﭘ', isolated: 'ﭖ', medial: 'ﭙ', final: 'ﭗ' },
37682
37683     1670: { initial: 'ﭼ', isolated: 'ﭺ', medial: 'ﭽ', final: 'ﭻ' },
37684     1603: { initial: 'ﻛ', isolated: 'ﻙ', medial: 'ﻜ', final: 'ﻚ' },
37685     1705: { initial: 'ﻛ', isolated: 'ﮎ', medial: 'ﻜ', final: 'ﮏ' },
37686     1711: { initial: 'ﮔ', isolated: 'ﮒ', medial: 'ﮕ', final: 'ﮓ' },
37687     1740: { initial: 'ﻳ', isolated: 'ﻯ', medial: 'ﻴ', final: 'ﻰ' },
37688     5000: { initial: 'ﻻ', isolated: 'ﻻ', medial: '', final: 'ﻼ' }
37689 };
37690
37691
37692 function fixArabicScriptTextForSvg(inputText) {
37693     var context = true;
37694     var ret = '';
37695     var rtlBuffer = [];
37696
37697     for (var i = 0, l = inputText.length; i < l; i++) {
37698         var code = inputText[i].charCodeAt(0);
37699         var nextCode = inputText[i + 1] ? inputText[i + 1].charCodeAt(0) : 0;
37700
37701         if (!chars$1[code]) {
37702             if (code === 32 && rtlBuffer.length) {
37703               // whitespace
37704               rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
37705             } else {
37706               // non-RTL character
37707               ret += rtlBuffer.reverse().join('') + inputText[i];
37708               rtlBuffer = [];
37709             }
37710             continue;
37711         }
37712         if (context) {
37713             if (i === l - 1 || nextCode === 32) {
37714                 rtlBuffer.push(chars$1[code].isolated);
37715             } else {
37716                 // special case for لا
37717                 if (code === 1604 && nextCode === 1575) {
37718                     rtlBuffer.push(chars$1[5000].initial);
37719                     i++;
37720                     context = true;
37721                     continue;
37722                 }
37723                 rtlBuffer.push(chars$1[code].initial);
37724             }
37725         } else {
37726             if (i === l - 1 || nextCode === 32){
37727                 rtlBuffer.push(chars$1[code].final);
37728             } else {
37729                 // special case for ﻼ
37730                 if (code === 1604 && nextCode === 1575){
37731                     rtlBuffer.push(chars$1[5000].final);
37732                     i++;
37733                     context = true;
37734                     continue;
37735                 }
37736                 if (chars$1[code].medial === ''){
37737                     rtlBuffer.push(chars$1[code].final);
37738                 } else {
37739                     rtlBuffer.push(chars$1[code].medial);
37740                 }
37741             }
37742         }
37743         context = (chars$1[code].medial === '') || nextCode === 32;
37744     }
37745
37746     ret += rtlBuffer.reverse().join('');
37747     return ret;
37748 }
37749
37750 function utilTagText(entity) {
37751     return entries(entity.tags).map(function(e) {
37752         return e.key + '=' + e.value;
37753     }).join(', ');
37754 }
37755
37756
37757 function utilEntitySelector(ids) {
37758     return ids.length ? '.' + ids.join(',.') : 'nothing';
37759 }
37760
37761
37762 function utilEntityOrMemberSelector(ids, graph) {
37763     var s = utilEntitySelector(ids);
37764
37765     ids.forEach(function(id) {
37766         var entity = graph.hasEntity(id);
37767         if (entity && entity.type === 'relation') {
37768             entity.members.forEach(function(member) {
37769                 s += ',.' + member.id;
37770             });
37771         }
37772     });
37773
37774     return s;
37775 }
37776
37777
37778 function utilGetAllNodes(ids, graph) {
37779     var seen = {};
37780     var nodes = [];
37781     ids.forEach(getNodes);
37782     return nodes;
37783
37784     function getNodes(id) {
37785         if (seen[id]) return;
37786         seen[id] = true;
37787
37788         var entity = graph.hasEntity(id);
37789         if (!entity) return;
37790
37791         if (entity.type === 'node') {
37792             nodes.push(entity);
37793         } else if (entity.type === 'way') {
37794             entity.nodes.forEach(getNodes);
37795         } else {
37796             entity.members.map(function(member) { return member.id; }).forEach(getNodes);
37797         }
37798     }
37799 }
37800
37801
37802 function utilDisplayName(entity) {
37803     var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37804         name = entity.tags[localizedNameKey] || entity.tags.name || '',
37805         network = entity.tags.cycle_network || entity.tags.network;
37806
37807     if (!name && entity.tags.ref) {
37808         name = entity.tags.ref;
37809         if (network) {
37810             name = network + ' ' + name;
37811         }
37812     }
37813
37814     return name;
37815 }
37816
37817
37818 function utilDisplayNameForPath(entity) {
37819     var name = utilDisplayName(entity);
37820     var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
37821     var arabicRegex = /[\u0600-\u06FF]/g;
37822
37823     if (!isFirefox && name && arabicRegex.test(name)) {
37824         name = fixArabicScriptTextForSvg(name);
37825     }
37826
37827     return name;
37828 }
37829
37830
37831 function utilDisplayType(id) {
37832     return {
37833         n: t('inspector.node'),
37834         w: t('inspector.way'),
37835         r: t('inspector.relation')
37836     }[id.charAt(0)];
37837 }
37838
37839
37840 function utilStringQs(str) {
37841     return str.split('&').reduce(function(obj, pair){
37842         var parts = pair.split('=');
37843         if (parts.length === 2) {
37844             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37845         }
37846         return obj;
37847     }, {});
37848 }
37849
37850
37851 function utilQsString(obj, noencode) {
37852     function softEncode(s) {
37853       // encode everything except special characters used in certain hash parameters:
37854       // "/" in map states, ":", ",", {" and "}" in background
37855       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37856     }
37857     return Object.keys(obj).sort().map(function(key) {
37858         return encodeURIComponent(key) + '=' + (
37859             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37860     }).join('&');
37861 }
37862
37863
37864 function utilPrefixDOMProperty(property) {
37865     var prefixes = ['webkit', 'ms', 'moz', 'o'],
37866         i = -1,
37867         n = prefixes.length,
37868         s = document.body;
37869
37870     if (property in s)
37871         return property;
37872
37873     property = property.substr(0, 1).toUpperCase() + property.substr(1);
37874
37875     while (++i < n)
37876         if (prefixes[i] + property in s)
37877             return prefixes[i] + property;
37878
37879     return false;
37880 }
37881
37882
37883 function utilPrefixCSSProperty(property) {
37884     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37885         i = -1,
37886         n = prefixes.length,
37887         s = document.body.style;
37888
37889     if (property.toLowerCase() in s)
37890         return property.toLowerCase();
37891
37892     while (++i < n)
37893         if (prefixes[i] + property in s)
37894             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37895
37896     return false;
37897 }
37898
37899
37900 var transformProperty;
37901 function utilSetTransform(el, x, y, scale) {
37902     var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37903         translate = utilDetect().opera ?
37904             'translate('   + x + 'px,' + y + 'px)' :
37905             'translate3d(' + x + 'px,' + y + 'px,0)';
37906     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37907 }
37908
37909
37910 // Calculates Levenshtein distance between two strings
37911 // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
37912 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37913 function utilEditDistance(a, b) {
37914     a = remove$1(a.toLowerCase());
37915     b = remove$1(b.toLowerCase());
37916     if (a.length === 0) return b.length;
37917     if (b.length === 0) return a.length;
37918     var matrix = [];
37919     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37920     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37921     for (i = 1; i <= b.length; i++) {
37922         for (j = 1; j <= a.length; j++) {
37923             if (b.charAt(i-1) === a.charAt(j-1)) {
37924                 matrix[i][j] = matrix[i-1][j-1];
37925             } else {
37926                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37927                     Math.min(matrix[i][j-1] + 1, // insertion
37928                     matrix[i-1][j] + 1)); // deletion
37929             }
37930         }
37931     }
37932     return matrix[b.length][a.length];
37933 }
37934
37935
37936 // a d3.mouse-alike which
37937 // 1. Only works on HTML elements, not SVG
37938 // 2. Does not cause style recalculation
37939 function utilFastMouse(container) {
37940     var rect = container.getBoundingClientRect(),
37941         rectLeft = rect.left,
37942         rectTop = rect.top,
37943         clientLeft = +container.clientLeft,
37944         clientTop = +container.clientTop;
37945     if (textDirection === 'rtl') {
37946         rectLeft = 0;
37947     }
37948     return function(e) {
37949         return [
37950             e.clientX - rectLeft - clientLeft,
37951             e.clientY - rectTop - clientTop];
37952     };
37953 }
37954
37955
37956 /* eslint-disable no-proto */
37957 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37958 /* eslint-enable no-proto */
37959
37960
37961 function utilAsyncMap(inputs, func, callback) {
37962     var remaining = inputs.length,
37963         results = [],
37964         errors = [];
37965
37966     inputs.forEach(function(d, i) {
37967         func(d, function done(err, data) {
37968             errors[i] = err;
37969             results[i] = data;
37970             remaining--;
37971             if (!remaining) callback(errors, results);
37972         });
37973     });
37974 }
37975
37976
37977 // wraps an index to an interval [0..length-1]
37978 function utilWrap(index, length) {
37979     if (index < 0)
37980         index += Math.ceil(-index/length)*length;
37981     return index % length;
37982 }
37983
37984
37985 /**
37986  * a replacement for functor
37987  *
37988  * @param {*} value any value
37989  * @returns {Function} a function that returns that value or the value if it's a function
37990  */
37991 function utilFunctor(value) {
37992     if (typeof value === 'function') return value;
37993     return function() {
37994         return value;
37995     };
37996 }
37997
37998 // A per-domain session mutex backed by a cookie and dead man's
37999 // switch. If the session crashes, the mutex will auto-release
38000 // after 5 seconds.
38001
38002 function utilSessionMutex(name) {
38003     var mutex = {},
38004         intervalID;
38005
38006     function renew() {
38007         var expires = new Date();
38008         expires.setSeconds(expires.getSeconds() + 5);
38009         document.cookie = name + '=1; expires=' + expires.toUTCString();
38010     }
38011
38012     mutex.lock = function() {
38013         if (intervalID) return true;
38014         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
38015         if (cookie) return false;
38016         renew();
38017         intervalID = window.setInterval(renew, 4000);
38018         return true;
38019     };
38020
38021     mutex.unlock = function() {
38022         if (!intervalID) return;
38023         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
38024         clearInterval(intervalID);
38025         intervalID = null;
38026     };
38027
38028     mutex.locked = function() {
38029         return !!intervalID;
38030     };
38031
38032     return mutex;
38033 }
38034
38035 function utilSuggestNames(preset, suggestions) {
38036     preset = preset.id.split('/', 2);
38037     var k = preset[0],
38038         v = preset[1];
38039
38040     return function(value, callback) {
38041         var result = [];
38042         if (value && value.length > 2) {
38043             if (suggestions[k] && suggestions[k][v]) {
38044                 for (var sugg in suggestions[k][v]) {
38045                     var dist = utilEditDistance(value, sugg.substring(0, value.length));
38046                     if (dist < 3) {
38047                         result.push({
38048                             title: sugg,
38049                             value: sugg,
38050                             dist: dist
38051                         });
38052                     }
38053                 }
38054             }
38055             result.sort(function(a, b) {
38056                 return a.dist - b.dist;
38057             });
38058         }
38059         result = result.slice(0,3);
38060         callback(result);
38061     };
38062 }
38063
38064 function utilTriggerEvent(target, type) {
38065     target.each(function() {
38066         var evt = document.createEvent('HTMLEvents');
38067         evt.initEvent(type, true, true);
38068         this.dispatchEvent(evt);
38069     });
38070 }
38071
38072 // Like selection.property('value', ...), but avoids no-op value sets,
38073 // which can result in layout/repaint thrashing in some situations.
38074 function utilGetSetValue(selection, value) {
38075     function d3_selection_value(value) {
38076         function valueNull() {
38077             delete this.value;
38078         }
38079
38080         function valueConstant() {
38081             if (this.value !== value) {
38082                 this.value = value;
38083             }
38084         }
38085
38086         function valueFunction() {
38087             var x = value.apply(this, arguments);
38088             if (x == null) {
38089                 delete this.value;
38090             } else if (this.value !== x) {
38091                 this.value = x;
38092             }
38093         }
38094
38095         return value == null
38096             ? valueNull : (typeof value === 'function'
38097             ? valueFunction : valueConstant);
38098     }
38099
38100     if (arguments.length === 1) {
38101         return selection.property('value');
38102     }
38103
38104     return selection.each(d3_selection_value(value));
38105 }
38106
38107 function validationDeprecatedTag() {
38108
38109     var validation = function(changes) {
38110         var warnings = [];
38111         for (var i = 0; i < changes.created.length; i++) {
38112             var change = changes.created[i],
38113                 deprecatedTags = change.deprecatedTags();
38114
38115             if (!lodash.isEmpty(deprecatedTags)) {
38116                 var tags = utilTagText({ tags: deprecatedTags });
38117                 warnings.push({
38118                     id: 'deprecated_tags',
38119                     message: t('validations.deprecated_tags', { tags: tags }),
38120                     entity: change
38121                 });
38122             }
38123         }
38124
38125         return warnings;
38126     };
38127
38128
38129     return validation;
38130 }
38131
38132 function validationDisconnectedHighway() {
38133
38134
38135     function isDisconnectedHighway(entity, graph) {
38136         if (!entity.tags.highway) return false;
38137         if (entity.geometry(graph) !== 'line') return false;
38138
38139         return graph.childNodes(entity)
38140             .every(function(vertex) {
38141                 return graph.parentWays(vertex)
38142                     .filter(function(parent) {
38143                         return parent.tags.highway && parent !== entity;
38144                     })
38145                     .length === 0;
38146             });
38147     }
38148
38149
38150     var validation = function(changes, graph) {
38151         var warnings = [];
38152         for (var i = 0; i < changes.created.length; i++) {
38153             var entity = changes.created[i];
38154
38155             if (isDisconnectedHighway(entity, graph)) {
38156                 warnings.push({
38157                     id: 'missing_tag',
38158                     message: t('validations.disconnected_highway'),
38159                     tooltip: t('validations.disconnected_highway_tooltip'),
38160                     entity: entity
38161                 });
38162             }
38163         }
38164
38165         return warnings;
38166     };
38167
38168
38169     return validation;
38170 }
38171
38172 function validationManyDeletions() {
38173     var threshold = 100;
38174
38175     var validation = function(changes) {
38176         var warnings = [];
38177         if (changes.deleted.length > threshold) {
38178             warnings.push({
38179                 id: 'many_deletions',
38180                 message: t('validations.many_deletions', { n: changes.deleted.length })
38181             });
38182         }
38183
38184         return warnings;
38185     };
38186
38187
38188     return validation;
38189 }
38190
38191 function validationMissingTag() {
38192
38193     // Slightly stricter check than Entity#isUsed (#3091)
38194     function hasTags(entity, graph) {
38195         return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
38196             graph.parentRelations(entity).length > 0;
38197     }
38198
38199     var validation = function(changes, graph) {
38200         var types = ['point', 'line', 'area', 'relation'],
38201             warnings = [];
38202
38203         for (var i = 0; i < changes.created.length; i++) {
38204             var change = changes.created[i],
38205                 geometry = change.geometry(graph);
38206
38207             if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
38208                 warnings.push({
38209                     id: 'missing_tag',
38210                     message: t('validations.untagged_' + geometry),
38211                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
38212                     entity: change
38213                 });
38214             }
38215         }
38216
38217         return warnings;
38218     };
38219
38220
38221     return validation;
38222 }
38223
38224 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
38225 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
38226 function validationTagSuggestsArea() {
38227
38228     function tagSuggestsArea(tags) {
38229         if (lodash.isEmpty(tags)) return false;
38230
38231         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
38232         for (var i = 0; i < presence.length; i++) {
38233             if (tags[presence[i]] !== undefined) {
38234                 return presence[i] + '=' + tags[presence[i]];
38235             }
38236         }
38237
38238         if (tags.building && tags.building === 'yes') return 'building=yes';
38239     }
38240
38241
38242     var validation = function(changes, graph) {
38243         var warnings = [];
38244         for (var i = 0; i < changes.created.length; i++) {
38245             var change = changes.created[i],
38246                 geometry = change.geometry(graph),
38247                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
38248
38249             if (suggestion) {
38250                 warnings.push({
38251                     id: 'tag_suggests_area',
38252                     message: t('validations.tag_suggests_area', { tag: suggestion }),
38253                     entity: change
38254                 });
38255             }
38256         }
38257
38258         return warnings;
38259     };
38260
38261
38262     return validation;
38263 }
38264
38265
38266
38267 var Validations = Object.freeze({
38268         validationDeprecatedTag: validationDeprecatedTag,
38269         validationDisconnectedHighway: validationDisconnectedHighway,
38270         validationManyDeletions: validationManyDeletions,
38271         validationMissingTag: validationMissingTag,
38272         validationTagSuggestsArea: validationTagSuggestsArea
38273 });
38274
38275 /*
38276     iD.Difference represents the difference between two graphs.
38277     It knows how to calculate the set of entities that were
38278     created, modified, or deleted, and also contains the logic
38279     for recursively extending a difference to the complete set
38280     of entities that will require a redraw, taking into account
38281     child and parent relationships.
38282  */
38283 function coreDifference(base, head) {
38284     var changes = {},
38285         difference = {},
38286         length = 0;
38287
38288
38289     function changed(h, b) {
38290         return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
38291     }
38292
38293
38294     lodash.each(head.entities, function(h, id) {
38295         var b = base.entities[id];
38296         if (changed(h, b)) {
38297             changes[id] = {base: b, head: h};
38298             length++;
38299         }
38300     });
38301
38302
38303     lodash.each(base.entities, function(b, id) {
38304         var h = head.entities[id];
38305         if (!changes[id] && changed(h, b)) {
38306             changes[id] = {base: b, head: h};
38307             length++;
38308         }
38309     });
38310
38311
38312     function addParents(parents, result) {
38313         for (var i = 0; i < parents.length; i++) {
38314             var parent = parents[i];
38315
38316             if (parent.id in result)
38317                 continue;
38318
38319             result[parent.id] = parent;
38320             addParents(head.parentRelations(parent), result);
38321         }
38322     }
38323
38324
38325     difference.length = function() {
38326         return length;
38327     };
38328
38329
38330     difference.changes = function() {
38331         return changes;
38332     };
38333
38334
38335     difference.extantIDs = function() {
38336         var result = [];
38337         lodash.each(changes, function(change, id) {
38338             if (change.head) result.push(id);
38339         });
38340         return result;
38341     };
38342
38343
38344     difference.modified = function() {
38345         var result = [];
38346         lodash.each(changes, function(change) {
38347             if (change.base && change.head) result.push(change.head);
38348         });
38349         return result;
38350     };
38351
38352
38353     difference.created = function() {
38354         var result = [];
38355         lodash.each(changes, function(change) {
38356             if (!change.base && change.head) result.push(change.head);
38357         });
38358         return result;
38359     };
38360
38361
38362     difference.deleted = function() {
38363         var result = [];
38364         lodash.each(changes, function(change) {
38365             if (change.base && !change.head) result.push(change.base);
38366         });
38367         return result;
38368     };
38369
38370
38371     difference.summary = function() {
38372         var relevant = {};
38373
38374         function addEntity(entity, graph, changeType) {
38375             relevant[entity.id] = {
38376                 entity: entity,
38377                 graph: graph,
38378                 changeType: changeType
38379             };
38380         }
38381
38382         function addParents(entity) {
38383             var parents = head.parentWays(entity);
38384             for (var j = parents.length - 1; j >= 0; j--) {
38385                 var parent = parents[j];
38386                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
38387             }
38388         }
38389
38390         lodash.each(changes, function(change) {
38391             if (change.head && change.head.geometry(head) !== 'vertex') {
38392                 addEntity(change.head, head, change.base ? 'modified' : 'created');
38393
38394             } else if (change.base && change.base.geometry(base) !== 'vertex') {
38395                 addEntity(change.base, base, 'deleted');
38396
38397             } else if (change.base && change.head) { // modified vertex
38398                 var moved    = !lodash.isEqual(change.base.loc,  change.head.loc),
38399                     retagged = !lodash.isEqual(change.base.tags, change.head.tags);
38400
38401                 if (moved) {
38402                     addParents(change.head);
38403                 }
38404
38405                 if (retagged || (moved && change.head.hasInterestingTags())) {
38406                     addEntity(change.head, head, 'modified');
38407                 }
38408
38409             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
38410                 addEntity(change.head, head, 'created');
38411
38412             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
38413                 addEntity(change.base, base, 'deleted');
38414             }
38415         });
38416
38417         return values(relevant);
38418     };
38419
38420
38421     difference.complete = function(extent$$1) {
38422         var result = {}, id, change;
38423
38424         for (id in changes) {
38425             change = changes[id];
38426
38427             var h = change.head,
38428                 b = change.base,
38429                 entity = h || b;
38430
38431             if (extent$$1 &&
38432                 (!h || !h.intersects(extent$$1, head)) &&
38433                 (!b || !b.intersects(extent$$1, base)))
38434                 continue;
38435
38436             result[id] = h;
38437
38438             if (entity.type === 'way') {
38439                 var nh = h ? h.nodes : [],
38440                     nb = b ? b.nodes : [],
38441                     diff, i;
38442
38443                 diff = lodash.difference(nh, nb);
38444                 for (i = 0; i < diff.length; i++) {
38445                     result[diff[i]] = head.hasEntity(diff[i]);
38446                 }
38447
38448                 diff = lodash.difference(nb, nh);
38449                 for (i = 0; i < diff.length; i++) {
38450                     result[diff[i]] = head.hasEntity(diff[i]);
38451                 }
38452             }
38453
38454             addParents(head.parentWays(entity), result);
38455             addParents(head.parentRelations(entity), result);
38456         }
38457
38458         return result;
38459     };
38460
38461
38462     return difference;
38463 }
38464
38465 function coreGraph$$1(other, mutable) {
38466     if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38467
38468     if (other instanceof coreGraph$$1) {
38469         var base = other.base();
38470         this.entities = lodash.assign(Object.create(base.entities), other.entities);
38471         this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38472         this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38473
38474     } else {
38475         this.entities = Object.create({});
38476         this._parentWays = Object.create({});
38477         this._parentRels = Object.create({});
38478         this.rebase(other || [], [this]);
38479     }
38480
38481     this.transients = {};
38482     this._childNodes = {};
38483     this.frozen = !mutable;
38484 }
38485
38486
38487 coreGraph$$1.prototype = {
38488
38489     hasEntity: function(id) {
38490         return this.entities[id];
38491     },
38492
38493
38494     entity: function(id) {
38495         var entity = this.entities[id];
38496         if (!entity) {
38497             throw new Error('entity ' + id + ' not found');
38498         }
38499         return entity;
38500     },
38501
38502
38503     transient: function(entity, key, fn) {
38504         var id = entity.id,
38505             transients = this.transients[id] ||
38506             (this.transients[id] = {});
38507
38508         if (transients[key] !== undefined) {
38509             return transients[key];
38510         }
38511
38512         transients[key] = fn.call(entity);
38513
38514         return transients[key];
38515     },
38516
38517
38518     parentWays: function(entity) {
38519         var parents = this._parentWays[entity.id],
38520             result = [];
38521
38522         if (parents) {
38523             for (var i = 0; i < parents.length; i++) {
38524                 result.push(this.entity(parents[i]));
38525             }
38526         }
38527         return result;
38528     },
38529
38530
38531     isPoi: function(entity) {
38532         var parentWays = this._parentWays[entity.id];
38533         return !parentWays || parentWays.length === 0;
38534     },
38535
38536
38537     isShared: function(entity) {
38538         var parentWays = this._parentWays[entity.id];
38539         return parentWays && parentWays.length > 1;
38540     },
38541
38542
38543     parentRelations: function(entity) {
38544         var parents = this._parentRels[entity.id],
38545             result = [];
38546
38547         if (parents) {
38548             for (var i = 0; i < parents.length; i++) {
38549                 result.push(this.entity(parents[i]));
38550             }
38551         }
38552         return result;
38553     },
38554
38555
38556     childNodes: function(entity) {
38557         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38558         if (!entity.nodes) return [];
38559
38560         var nodes = [];
38561         for (var i = 0; i < entity.nodes.length; i++) {
38562             nodes[i] = this.entity(entity.nodes[i]);
38563         }
38564
38565         if (debug) Object.freeze(nodes);
38566
38567         this._childNodes[entity.id] = nodes;
38568         return this._childNodes[entity.id];
38569     },
38570
38571
38572     base: function() {
38573         return {
38574             'entities': utilGetPrototypeOf(this.entities),
38575             'parentWays': utilGetPrototypeOf(this._parentWays),
38576             'parentRels': utilGetPrototypeOf(this._parentRels)
38577         };
38578     },
38579
38580
38581     // Unlike other graph methods, rebase mutates in place. This is because it
38582     // is used only during the history operation that merges newly downloaded
38583     // data into each state. To external consumers, it should appear as if the
38584     // graph always contained the newly downloaded data.
38585     rebase: function(entities, stack, force) {
38586         var base = this.base(),
38587             i, j, k, id;
38588
38589         for (i = 0; i < entities.length; i++) {
38590             var entity = entities[i];
38591
38592             if (!entity.visible || (!force && base.entities[entity.id]))
38593                 continue;
38594
38595             // Merging data into the base graph
38596             base.entities[entity.id] = entity;
38597             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38598
38599             // Restore provisionally-deleted nodes that are discovered to have an extant parent
38600             if (entity.type === 'way') {
38601                 for (j = 0; j < entity.nodes.length; j++) {
38602                     id = entity.nodes[j];
38603                     for (k = 1; k < stack.length; k++) {
38604                         var ents = stack[k].entities;
38605                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38606                             delete ents[id];
38607                         }
38608                     }
38609                 }
38610             }
38611         }
38612
38613         for (i = 0; i < stack.length; i++) {
38614             stack[i]._updateRebased();
38615         }
38616     },
38617
38618
38619     _updateRebased: function() {
38620         var base = this.base(),
38621             i, k, child, id, keys;
38622
38623         keys = Object.keys(this._parentWays);
38624         for (i = 0; i < keys.length; i++) {
38625             child = keys[i];
38626             if (base.parentWays[child]) {
38627                 for (k = 0; k < base.parentWays[child].length; k++) {
38628                     id = base.parentWays[child][k];
38629                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38630                         this._parentWays[child].push(id);
38631                     }
38632                 }
38633             }
38634         }
38635
38636         keys = Object.keys(this._parentRels);
38637         for (i = 0; i < keys.length; i++) {
38638             child = keys[i];
38639             if (base.parentRels[child]) {
38640                 for (k = 0; k < base.parentRels[child].length; k++) {
38641                     id = base.parentRels[child][k];
38642                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38643                         this._parentRels[child].push(id);
38644                     }
38645                 }
38646             }
38647         }
38648
38649         this.transients = {};
38650
38651         // this._childNodes is not updated, under the assumption that
38652         // ways are always downloaded with their child nodes.
38653     },
38654
38655
38656     // Updates calculated properties (parentWays, parentRels) for the specified change
38657     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38658
38659         parentWays = parentWays || this._parentWays;
38660         parentRels = parentRels || this._parentRels;
38661
38662         var type = entity && entity.type || oldentity && oldentity.type,
38663             removed, added, ways, rels, i;
38664
38665
38666         if (type === 'way') {
38667
38668             // Update parentWays
38669             if (oldentity && entity) {
38670                 removed = lodash.difference(oldentity.nodes, entity.nodes);
38671                 added = lodash.difference(entity.nodes, oldentity.nodes);
38672             } else if (oldentity) {
38673                 removed = oldentity.nodes;
38674                 added = [];
38675             } else if (entity) {
38676                 removed = [];
38677                 added = entity.nodes;
38678             }
38679             for (i = 0; i < removed.length; i++) {
38680                 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38681             }
38682             for (i = 0; i < added.length; i++) {
38683                 ways = lodash.without(parentWays[added[i]], entity.id);
38684                 ways.push(entity.id);
38685                 parentWays[added[i]] = ways;
38686             }
38687
38688         } else if (type === 'relation') {
38689
38690             // Update parentRels
38691             if (oldentity && entity) {
38692                 removed = lodash.difference(oldentity.members, entity.members);
38693                 added = lodash.difference(entity.members, oldentity);
38694             } else if (oldentity) {
38695                 removed = oldentity.members;
38696                 added = [];
38697             } else if (entity) {
38698                 removed = [];
38699                 added = entity.members;
38700             }
38701             for (i = 0; i < removed.length; i++) {
38702                 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38703             }
38704             for (i = 0; i < added.length; i++) {
38705                 rels = lodash.without(parentRels[added[i].id], entity.id);
38706                 rels.push(entity.id);
38707                 parentRels[added[i].id] = rels;
38708             }
38709         }
38710     },
38711
38712
38713     replace: function(entity) {
38714         if (this.entities[entity.id] === entity)
38715             return this;
38716
38717         return this.update(function() {
38718             this._updateCalculated(this.entities[entity.id], entity);
38719             this.entities[entity.id] = entity;
38720         });
38721     },
38722
38723
38724     remove: function(entity) {
38725         return this.update(function() {
38726             this._updateCalculated(entity, undefined);
38727             this.entities[entity.id] = undefined;
38728         });
38729     },
38730
38731
38732     revert: function(id) {
38733         var baseEntity = this.base().entities[id],
38734             headEntity = this.entities[id];
38735
38736         if (headEntity === baseEntity)
38737             return this;
38738
38739         return this.update(function() {
38740             this._updateCalculated(headEntity, baseEntity);
38741             delete this.entities[id];
38742         });
38743     },
38744
38745
38746     update: function() {
38747         var graph = this.frozen ? coreGraph$$1(this, true) : this;
38748
38749         for (var i = 0; i < arguments.length; i++) {
38750             arguments[i].call(graph, graph);
38751         }
38752
38753         if (this.frozen) graph.frozen = true;
38754
38755         return graph;
38756     },
38757
38758
38759     // Obliterates any existing entities
38760     load: function(entities) {
38761         var base = this.base();
38762         this.entities = Object.create(base.entities);
38763
38764         for (var i in entities) {
38765             this.entities[i] = entities[i];
38766             this._updateCalculated(base.entities[i], this.entities[i]);
38767         }
38768
38769         return this;
38770     }
38771 };
38772
38773 var index$10 = partialSort;
38774
38775 // Floyd-Rivest selection algorithm:
38776 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38777 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38778
38779 function partialSort(arr, k, left, right, compare) {
38780     left = left || 0;
38781     right = right || (arr.length - 1);
38782     compare = compare || defaultCompare;
38783
38784     while (right > left) {
38785         if (right - left > 600) {
38786             var n = right - left + 1;
38787             var m = k - left + 1;
38788             var z = Math.log(n);
38789             var s = 0.5 * Math.exp(2 * z / 3);
38790             var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38791             var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38792             var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38793             partialSort(arr, k, newLeft, newRight, compare);
38794         }
38795
38796         var t = arr[k];
38797         var i = left;
38798         var j = right;
38799
38800         swap(arr, left, k);
38801         if (compare(arr[right], t) > 0) swap(arr, left, right);
38802
38803         while (i < j) {
38804             swap(arr, i, j);
38805             i++;
38806             j--;
38807             while (compare(arr[i], t) < 0) i++;
38808             while (compare(arr[j], t) > 0) j--;
38809         }
38810
38811         if (compare(arr[left], t) === 0) swap(arr, left, j);
38812         else {
38813             j++;
38814             swap(arr, j, right);
38815         }
38816
38817         if (j <= k) left = j + 1;
38818         if (k <= j) right = j - 1;
38819     }
38820 }
38821
38822 function swap(arr, i, j) {
38823     var tmp = arr[i];
38824     arr[i] = arr[j];
38825     arr[j] = tmp;
38826 }
38827
38828 function defaultCompare(a, b) {
38829     return a < b ? -1 : a > b ? 1 : 0;
38830 }
38831
38832 var index$9 = rbush;
38833
38834 var quickselect = index$10;
38835
38836 function rbush(maxEntries, format) {
38837     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38838
38839     // max entries in a node is 9 by default; min node fill is 40% for best performance
38840     this._maxEntries = Math.max(4, maxEntries || 9);
38841     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38842
38843     if (format) {
38844         this._initFormat(format);
38845     }
38846
38847     this.clear();
38848 }
38849
38850 rbush.prototype = {
38851
38852     all: function () {
38853         return this._all(this.data, []);
38854     },
38855
38856     search: function (bbox) {
38857
38858         var node = this.data,
38859             result = [],
38860             toBBox = this.toBBox;
38861
38862         if (!intersects$1(bbox, node)) return result;
38863
38864         var nodesToSearch = [],
38865             i, len, child, childBBox;
38866
38867         while (node) {
38868             for (i = 0, len = node.children.length; i < len; i++) {
38869
38870                 child = node.children[i];
38871                 childBBox = node.leaf ? toBBox(child) : child;
38872
38873                 if (intersects$1(bbox, childBBox)) {
38874                     if (node.leaf) result.push(child);
38875                     else if (contains$1(bbox, childBBox)) this._all(child, result);
38876                     else nodesToSearch.push(child);
38877                 }
38878             }
38879             node = nodesToSearch.pop();
38880         }
38881
38882         return result;
38883     },
38884
38885     collides: function (bbox) {
38886
38887         var node = this.data,
38888             toBBox = this.toBBox;
38889
38890         if (!intersects$1(bbox, node)) return false;
38891
38892         var nodesToSearch = [],
38893             i, len, child, childBBox;
38894
38895         while (node) {
38896             for (i = 0, len = node.children.length; i < len; i++) {
38897
38898                 child = node.children[i];
38899                 childBBox = node.leaf ? toBBox(child) : child;
38900
38901                 if (intersects$1(bbox, childBBox)) {
38902                     if (node.leaf || contains$1(bbox, childBBox)) return true;
38903                     nodesToSearch.push(child);
38904                 }
38905             }
38906             node = nodesToSearch.pop();
38907         }
38908
38909         return false;
38910     },
38911
38912     load: function (data) {
38913         if (!(data && data.length)) return this;
38914
38915         if (data.length < this._minEntries) {
38916             for (var i = 0, len = data.length; i < len; i++) {
38917                 this.insert(data[i]);
38918             }
38919             return this;
38920         }
38921
38922         // recursively build the tree with the given data from stratch using OMT algorithm
38923         var node = this._build(data.slice(), 0, data.length - 1, 0);
38924
38925         if (!this.data.children.length) {
38926             // save as is if tree is empty
38927             this.data = node;
38928
38929         } else if (this.data.height === node.height) {
38930             // split root if trees have the same height
38931             this._splitRoot(this.data, node);
38932
38933         } else {
38934             if (this.data.height < node.height) {
38935                 // swap trees if inserted one is bigger
38936                 var tmpNode = this.data;
38937                 this.data = node;
38938                 node = tmpNode;
38939             }
38940
38941             // insert the small tree into the large tree at appropriate level
38942             this._insert(node, this.data.height - node.height - 1, true);
38943         }
38944
38945         return this;
38946     },
38947
38948     insert: function (item) {
38949         if (item) this._insert(item, this.data.height - 1);
38950         return this;
38951     },
38952
38953     clear: function () {
38954         this.data = createNode([]);
38955         return this;
38956     },
38957
38958     remove: function (item, equalsFn) {
38959         if (!item) return this;
38960
38961         var node = this.data,
38962             bbox = this.toBBox(item),
38963             path = [],
38964             indexes = [],
38965             i, parent, index, goingUp;
38966
38967         // depth-first iterative tree traversal
38968         while (node || path.length) {
38969
38970             if (!node) { // go up
38971                 node = path.pop();
38972                 parent = path[path.length - 1];
38973                 i = indexes.pop();
38974                 goingUp = true;
38975             }
38976
38977             if (node.leaf) { // check current node
38978                 index = findItem(item, node.children, equalsFn);
38979
38980                 if (index !== -1) {
38981                     // item found, remove the item and condense tree upwards
38982                     node.children.splice(index, 1);
38983                     path.push(node);
38984                     this._condense(path);
38985                     return this;
38986                 }
38987             }
38988
38989             if (!goingUp && !node.leaf && contains$1(node, bbox)) { // go down
38990                 path.push(node);
38991                 indexes.push(i);
38992                 i = 0;
38993                 parent = node;
38994                 node = node.children[0];
38995
38996             } else if (parent) { // go right
38997                 i++;
38998                 node = parent.children[i];
38999                 goingUp = false;
39000
39001             } else node = null; // nothing found
39002         }
39003
39004         return this;
39005     },
39006
39007     toBBox: function (item) { return item; },
39008
39009     compareMinX: compareNodeMinX,
39010     compareMinY: compareNodeMinY,
39011
39012     toJSON: function () { return this.data; },
39013
39014     fromJSON: function (data) {
39015         this.data = data;
39016         return this;
39017     },
39018
39019     _all: function (node, result) {
39020         var nodesToSearch = [];
39021         while (node) {
39022             if (node.leaf) result.push.apply(result, node.children);
39023             else nodesToSearch.push.apply(nodesToSearch, node.children);
39024
39025             node = nodesToSearch.pop();
39026         }
39027         return result;
39028     },
39029
39030     _build: function (items, left, right, height) {
39031
39032         var N = right - left + 1,
39033             M = this._maxEntries,
39034             node;
39035
39036         if (N <= M) {
39037             // reached leaf level; return leaf
39038             node = createNode(items.slice(left, right + 1));
39039             calcBBox(node, this.toBBox);
39040             return node;
39041         }
39042
39043         if (!height) {
39044             // target height of the bulk-loaded tree
39045             height = Math.ceil(Math.log(N) / Math.log(M));
39046
39047             // target number of root entries to maximize storage utilization
39048             M = Math.ceil(N / Math.pow(M, height - 1));
39049         }
39050
39051         node = createNode([]);
39052         node.leaf = false;
39053         node.height = height;
39054
39055         // split the items into M mostly square tiles
39056
39057         var N2 = Math.ceil(N / M),
39058             N1 = N2 * Math.ceil(Math.sqrt(M)),
39059             i, j, right2, right3;
39060
39061         multiSelect(items, left, right, N1, this.compareMinX);
39062
39063         for (i = left; i <= right; i += N1) {
39064
39065             right2 = Math.min(i + N1 - 1, right);
39066
39067             multiSelect(items, i, right2, N2, this.compareMinY);
39068
39069             for (j = i; j <= right2; j += N2) {
39070
39071                 right3 = Math.min(j + N2 - 1, right2);
39072
39073                 // pack each entry recursively
39074                 node.children.push(this._build(items, j, right3, height - 1));
39075             }
39076         }
39077
39078         calcBBox(node, this.toBBox);
39079
39080         return node;
39081     },
39082
39083     _chooseSubtree: function (bbox, node, level, path) {
39084
39085         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
39086
39087         while (true) {
39088             path.push(node);
39089
39090             if (node.leaf || path.length - 1 === level) break;
39091
39092             minArea = minEnlargement = Infinity;
39093
39094             for (i = 0, len = node.children.length; i < len; i++) {
39095                 child = node.children[i];
39096                 area = bboxArea(child);
39097                 enlargement = enlargedArea(bbox, child) - area;
39098
39099                 // choose entry with the least area enlargement
39100                 if (enlargement < minEnlargement) {
39101                     minEnlargement = enlargement;
39102                     minArea = area < minArea ? area : minArea;
39103                     targetNode = child;
39104
39105                 } else if (enlargement === minEnlargement) {
39106                     // otherwise choose one with the smallest area
39107                     if (area < minArea) {
39108                         minArea = area;
39109                         targetNode = child;
39110                     }
39111                 }
39112             }
39113
39114             node = targetNode || node.children[0];
39115         }
39116
39117         return node;
39118     },
39119
39120     _insert: function (item, level, isNode) {
39121
39122         var toBBox = this.toBBox,
39123             bbox = isNode ? item : toBBox(item),
39124             insertPath = [];
39125
39126         // find the best node for accommodating the item, saving all nodes along the path too
39127         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
39128
39129         // put the item into the node
39130         node.children.push(item);
39131         extend$1(node, bbox);
39132
39133         // split on node overflow; propagate upwards if necessary
39134         while (level >= 0) {
39135             if (insertPath[level].children.length > this._maxEntries) {
39136                 this._split(insertPath, level);
39137                 level--;
39138             } else break;
39139         }
39140
39141         // adjust bboxes along the insertion path
39142         this._adjustParentBBoxes(bbox, insertPath, level);
39143     },
39144
39145     // split overflowed node into two
39146     _split: function (insertPath, level) {
39147
39148         var node = insertPath[level],
39149             M = node.children.length,
39150             m = this._minEntries;
39151
39152         this._chooseSplitAxis(node, m, M);
39153
39154         var splitIndex = this._chooseSplitIndex(node, m, M);
39155
39156         var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
39157         newNode.height = node.height;
39158         newNode.leaf = node.leaf;
39159
39160         calcBBox(node, this.toBBox);
39161         calcBBox(newNode, this.toBBox);
39162
39163         if (level) insertPath[level - 1].children.push(newNode);
39164         else this._splitRoot(node, newNode);
39165     },
39166
39167     _splitRoot: function (node, newNode) {
39168         // split root node
39169         this.data = createNode([node, newNode]);
39170         this.data.height = node.height + 1;
39171         this.data.leaf = false;
39172         calcBBox(this.data, this.toBBox);
39173     },
39174
39175     _chooseSplitIndex: function (node, m, M) {
39176
39177         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
39178
39179         minOverlap = minArea = Infinity;
39180
39181         for (i = m; i <= M - m; i++) {
39182             bbox1 = distBBox(node, 0, i, this.toBBox);
39183             bbox2 = distBBox(node, i, M, this.toBBox);
39184
39185             overlap = intersectionArea(bbox1, bbox2);
39186             area = bboxArea(bbox1) + bboxArea(bbox2);
39187
39188             // choose distribution with minimum overlap
39189             if (overlap < minOverlap) {
39190                 minOverlap = overlap;
39191                 index = i;
39192
39193                 minArea = area < minArea ? area : minArea;
39194
39195             } else if (overlap === minOverlap) {
39196                 // otherwise choose distribution with minimum area
39197                 if (area < minArea) {
39198                     minArea = area;
39199                     index = i;
39200                 }
39201             }
39202         }
39203
39204         return index;
39205     },
39206
39207     // sorts node children by the best axis for split
39208     _chooseSplitAxis: function (node, m, M) {
39209
39210         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
39211             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
39212             xMargin = this._allDistMargin(node, m, M, compareMinX),
39213             yMargin = this._allDistMargin(node, m, M, compareMinY);
39214
39215         // if total distributions margin value is minimal for x, sort by minX,
39216         // otherwise it's already sorted by minY
39217         if (xMargin < yMargin) node.children.sort(compareMinX);
39218     },
39219
39220     // total margin of all possible split distributions where each node is at least m full
39221     _allDistMargin: function (node, m, M, compare) {
39222
39223         node.children.sort(compare);
39224
39225         var toBBox = this.toBBox,
39226             leftBBox = distBBox(node, 0, m, toBBox),
39227             rightBBox = distBBox(node, M - m, M, toBBox),
39228             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
39229             i, child;
39230
39231         for (i = m; i < M - m; i++) {
39232             child = node.children[i];
39233             extend$1(leftBBox, node.leaf ? toBBox(child) : child);
39234             margin += bboxMargin(leftBBox);
39235         }
39236
39237         for (i = M - m - 1; i >= m; i--) {
39238             child = node.children[i];
39239             extend$1(rightBBox, node.leaf ? toBBox(child) : child);
39240             margin += bboxMargin(rightBBox);
39241         }
39242
39243         return margin;
39244     },
39245
39246     _adjustParentBBoxes: function (bbox, path, level) {
39247         // adjust bboxes along the given tree path
39248         for (var i = level; i >= 0; i--) {
39249             extend$1(path[i], bbox);
39250         }
39251     },
39252
39253     _condense: function (path) {
39254         // go through the path, removing empty nodes and updating bboxes
39255         for (var i = path.length - 1, siblings; i >= 0; i--) {
39256             if (path[i].children.length === 0) {
39257                 if (i > 0) {
39258                     siblings = path[i - 1].children;
39259                     siblings.splice(siblings.indexOf(path[i]), 1);
39260
39261                 } else this.clear();
39262
39263             } else calcBBox(path[i], this.toBBox);
39264         }
39265     },
39266
39267     _initFormat: function (format) {
39268         // data format (minX, minY, maxX, maxY accessors)
39269
39270         // uses eval-type function compilation instead of just accepting a toBBox function
39271         // because the algorithms are very sensitive to sorting functions performance,
39272         // so they should be dead simple and without inner calls
39273
39274         var compareArr = ['return a', ' - b', ';'];
39275
39276         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
39277         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
39278
39279         this.toBBox = new Function('a',
39280             'return {minX: a' + format[0] +
39281             ', minY: a' + format[1] +
39282             ', maxX: a' + format[2] +
39283             ', maxY: a' + format[3] + '};');
39284     }
39285 };
39286
39287 function findItem(item, items, equalsFn) {
39288     if (!equalsFn) return items.indexOf(item);
39289
39290     for (var i = 0; i < items.length; i++) {
39291         if (equalsFn(item, items[i])) return i;
39292     }
39293     return -1;
39294 }
39295
39296 // calculate node's bbox from bboxes of its children
39297 function calcBBox(node, toBBox) {
39298     distBBox(node, 0, node.children.length, toBBox, node);
39299 }
39300
39301 // min bounding rectangle of node children from k to p-1
39302 function distBBox(node, k, p, toBBox, destNode) {
39303     if (!destNode) destNode = createNode(null);
39304     destNode.minX = Infinity;
39305     destNode.minY = Infinity;
39306     destNode.maxX = -Infinity;
39307     destNode.maxY = -Infinity;
39308
39309     for (var i = k, child; i < p; i++) {
39310         child = node.children[i];
39311         extend$1(destNode, node.leaf ? toBBox(child) : child);
39312     }
39313
39314     return destNode;
39315 }
39316
39317 function extend$1(a, b) {
39318     a.minX = Math.min(a.minX, b.minX);
39319     a.minY = Math.min(a.minY, b.minY);
39320     a.maxX = Math.max(a.maxX, b.maxX);
39321     a.maxY = Math.max(a.maxY, b.maxY);
39322     return a;
39323 }
39324
39325 function compareNodeMinX(a, b) { return a.minX - b.minX; }
39326 function compareNodeMinY(a, b) { return a.minY - b.minY; }
39327
39328 function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
39329 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
39330
39331 function enlargedArea(a, b) {
39332     return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
39333            (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
39334 }
39335
39336 function intersectionArea(a, b) {
39337     var minX = Math.max(a.minX, b.minX),
39338         minY = Math.max(a.minY, b.minY),
39339         maxX = Math.min(a.maxX, b.maxX),
39340         maxY = Math.min(a.maxY, b.maxY);
39341
39342     return Math.max(0, maxX - minX) *
39343            Math.max(0, maxY - minY);
39344 }
39345
39346 function contains$1(a, b) {
39347     return a.minX <= b.minX &&
39348            a.minY <= b.minY &&
39349            b.maxX <= a.maxX &&
39350            b.maxY <= a.maxY;
39351 }
39352
39353 function intersects$1(a, b) {
39354     return b.minX <= a.maxX &&
39355            b.minY <= a.maxY &&
39356            b.maxX >= a.minX &&
39357            b.maxY >= a.minY;
39358 }
39359
39360 function createNode(children) {
39361     return {
39362         children: children,
39363         height: 1,
39364         leaf: true,
39365         minX: Infinity,
39366         minY: Infinity,
39367         maxX: -Infinity,
39368         maxY: -Infinity
39369     };
39370 }
39371
39372 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
39373 // combines selection algorithm with binary divide & conquer approach
39374
39375 function multiSelect(arr, left, right, n, compare) {
39376     var stack = [left, right],
39377         mid;
39378
39379     while (stack.length) {
39380         right = stack.pop();
39381         left = stack.pop();
39382
39383         if (right - left <= n) continue;
39384
39385         mid = left + Math.ceil((right - left) / n / 2) * n;
39386         quickselect(arr, mid, left, right, compare);
39387
39388         stack.push(left, mid, mid, right);
39389     }
39390 }
39391
39392 function coreTree(head) {
39393     var rtree = index$9(),
39394         bboxes = {},
39395         tree = {};
39396
39397
39398     function entityBBox(entity) {
39399         var bbox = entity.extent(head).bbox();
39400         bbox.id = entity.id;
39401         bboxes[entity.id] = bbox;
39402         return bbox;
39403     }
39404
39405
39406     function updateParents(entity, insertions, memo) {
39407         head.parentWays(entity).forEach(function(way) {
39408             if (bboxes[way.id]) {
39409                 rtree.remove(bboxes[way.id]);
39410                 insertions[way.id] = way;
39411             }
39412             updateParents(way, insertions, memo);
39413         });
39414
39415         head.parentRelations(entity).forEach(function(relation) {
39416             if (memo[entity.id]) return;
39417             memo[entity.id] = true;
39418             if (bboxes[relation.id]) {
39419                 rtree.remove(bboxes[relation.id]);
39420                 insertions[relation.id] = relation;
39421             }
39422             updateParents(relation, insertions, memo);
39423         });
39424     }
39425
39426
39427     tree.rebase = function(entities, force) {
39428         var insertions = {};
39429
39430         for (var i = 0; i < entities.length; i++) {
39431             var entity = entities[i];
39432
39433             if (!entity.visible)
39434                 continue;
39435
39436             if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
39437                 if (!force) {
39438                     continue;
39439                 } else if (bboxes[entity.id]) {
39440                     rtree.remove(bboxes[entity.id]);
39441                 }
39442             }
39443
39444             insertions[entity.id] = entity;
39445             updateParents(entity, insertions, {});
39446         }
39447
39448         rtree.load(lodash.map(insertions, entityBBox));
39449
39450         return tree;
39451     };
39452
39453
39454     tree.intersects = function(extent, graph) {
39455         if (graph !== head) {
39456             var diff = coreDifference(head, graph),
39457                 insertions = {};
39458
39459             head = graph;
39460
39461             diff.deleted().forEach(function(entity) {
39462                 rtree.remove(bboxes[entity.id]);
39463                 delete bboxes[entity.id];
39464             });
39465
39466             diff.modified().forEach(function(entity) {
39467                 rtree.remove(bboxes[entity.id]);
39468                 insertions[entity.id] = entity;
39469                 updateParents(entity, insertions, {});
39470             });
39471
39472             diff.created().forEach(function(entity) {
39473                 insertions[entity.id] = entity;
39474             });
39475
39476             rtree.load(lodash.map(insertions, entityBBox));
39477         }
39478
39479         return rtree.search(extent.bbox()).map(function(bbox) {
39480             return head.entity(bbox.id);
39481         });
39482     };
39483
39484
39485     return tree;
39486 }
39487
39488 /*
39489  * This code is licensed under the MIT license.
39490  *
39491  * Copyright © 2013, iD authors.
39492  *
39493  * Portions copyright © 2011, Keith Cirkel
39494  * See https://github.com/keithamus/jwerty
39495  *
39496  */
39497 function d3keybinding(namespace$$1) {
39498     var bindings = [];
39499
39500     function matches(binding, event$$1) {
39501         for (var p in binding.event) {
39502             if (event$$1[p] !== binding.event[p])
39503                 return false;
39504         }
39505         return true;
39506     }
39507
39508     function testBindings(isCapturing) {
39509         for (var i = 0; i < bindings.length; i++) {
39510             var binding = bindings[i];
39511
39512             if (!!binding.capture === isCapturing && matches(binding, event)) {
39513                 binding.callback();
39514             }
39515         }
39516     }
39517
39518     function capture() {
39519         testBindings(true);
39520     }
39521
39522     function bubble() {
39523         var tagName = select(event.target).node().tagName;
39524         if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39525             return;
39526         }
39527         testBindings(false);
39528     }
39529
39530     function keybinding(selection$$1) {
39531         selection$$1 = selection$$1 || select(document);
39532         selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39533         selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39534         return keybinding;
39535     }
39536
39537     keybinding.off = function(selection$$1) {
39538         bindings = [];
39539         selection$$1 = selection$$1 || select(document);
39540         selection$$1.on('keydown.capture' + namespace$$1, null);
39541         selection$$1.on('keydown.bubble' + namespace$$1, null);
39542         return keybinding;
39543     };
39544
39545     keybinding.on = function(codes, callback, capture) {
39546         var arr = [].concat(codes);
39547         for (var i = 0; i < arr.length; i++) {
39548             var code = arr[i];
39549             var binding = {
39550                 event: {
39551                     keyCode: 0,
39552                     shiftKey: false,
39553                     ctrlKey: false,
39554                     altKey: false,
39555                     metaKey: false
39556                 },
39557                 capture: capture,
39558                 callback: callback
39559             };
39560
39561             code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39562
39563             for (var j = 0; j < code.length; j++) {
39564                 // Normalise matching errors
39565                 if (code[j] === '++') code[i] = '+';
39566
39567                 if (code[j] in d3keybinding.modifierCodes) {
39568                     binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39569                 } else if (code[j] in d3keybinding.keyCodes) {
39570                     binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39571                 }
39572             }
39573
39574             bindings.push(binding);
39575         }
39576
39577         return keybinding;
39578     };
39579
39580     return keybinding;
39581 }
39582
39583
39584 d3keybinding.modifierCodes = {
39585     // Shift key, ⇧
39586     '⇧': 16, shift: 16,
39587     // CTRL key, on Mac: ⌃
39588     '⌃': 17, ctrl: 17,
39589     // ALT key, on Mac: ⌥ (Alt)
39590     '⌥': 18, alt: 18, option: 18,
39591     // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39592     '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39593 };
39594
39595 d3keybinding.modifierProperties = {
39596     16: 'shiftKey',
39597     17: 'ctrlKey',
39598     18: 'altKey',
39599     91: 'metaKey'
39600 };
39601
39602 d3keybinding.keyCodes = {
39603     // Backspace key, on Mac: ⌫ (Backspace)
39604     '⌫': 8, backspace: 8,
39605     // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39606     '⇥': 9, '⇆': 9, tab: 9,
39607     // Return key, ↩
39608     '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39609     // Pause/Break key
39610     'pause': 19, 'pause-break': 19,
39611     // Caps Lock key, ⇪
39612     '⇪': 20, caps: 20, 'caps-lock': 20,
39613     // Escape key, on Mac: ⎋, on Windows: Esc
39614     '⎋': 27, escape: 27, esc: 27,
39615     // Space key
39616     space: 32,
39617     // Page-Up key, or pgup, on Mac: ↖
39618     '↖': 33, pgup: 33, 'page-up': 33,
39619     // Page-Down key, or pgdown, on Mac: ↘
39620     '↘': 34, pgdown: 34, 'page-down': 34,
39621     // END key, on Mac: ⇟
39622     '⇟': 35, end: 35,
39623     // HOME key, on Mac: ⇞
39624     '⇞': 36, home: 36,
39625     // Insert key, or ins
39626     ins: 45, insert: 45,
39627     // Delete key, on Mac: ⌦ (Delete)
39628     '⌦': 46, del: 46, 'delete': 46,
39629     // Left Arrow Key, or ←
39630     '←': 37, left: 37, 'arrow-left': 37,
39631     // Up Arrow Key, or ↑
39632     '↑': 38, up: 38, 'arrow-up': 38,
39633     // Right Arrow Key, or →
39634     '→': 39, right: 39, 'arrow-right': 39,
39635     // Up Arrow Key, or ↓
39636     '↓': 40, down: 40, 'arrow-down': 40,
39637     // odities, printing characters that come out wrong:
39638     // Firefox Equals
39639     'ffequals': 61,
39640     // Num-Multiply, or *
39641     '*': 106, star: 106, asterisk: 106, multiply: 106,
39642     // Num-Plus or +
39643     '+': 107, 'plus': 107,
39644     // Num-Subtract, or -
39645     '-': 109, subtract: 109,
39646     // Firefox Plus
39647     'ffplus': 171,
39648     // Firefox Minus
39649     'ffminus': 173,
39650     // Semicolon
39651     ';': 186, semicolon: 186,
39652     // = or equals
39653     '=': 187, 'equals': 187,
39654     // Comma, or ,
39655     ',': 188, comma: 188,
39656     // Dash / Underscore key
39657     'dash': 189,
39658     // Period, or ., or full-stop
39659     '.': 190, period: 190, 'full-stop': 190,
39660     // Slash, or /, or forward-slash
39661     '/': 191, slash: 191, 'forward-slash': 191,
39662     // Tick, or `, or back-quote
39663     '`': 192, tick: 192, 'back-quote': 192,
39664     // Open bracket, or [
39665     '[': 219, 'open-bracket': 219,
39666     // Back slash, or \
39667     '\\': 220, 'back-slash': 220,
39668     // Close backet, or ]
39669     ']': 221, 'close-bracket': 221,
39670     // Apostrophe, or Quote, or '
39671     '\'': 222, quote: 222, apostrophe: 222
39672 };
39673
39674 // NUMPAD 0-9
39675 var i$1 = 95;
39676 var n = 0;
39677 while (++i$1 < 106) {
39678     d3keybinding.keyCodes['num-' + n] = i$1;
39679     ++n;
39680 }
39681
39682 // 0-9
39683 i$1 = 47; n = 0;
39684 while (++i$1 < 58) {
39685     d3keybinding.keyCodes[n] = i$1;
39686     ++n;
39687 }
39688
39689 // F1-F25
39690 i$1 = 111; n = 1;
39691 while (++i$1 < 136) {
39692     d3keybinding.keyCodes['f' + n] = i$1;
39693     ++n;
39694 }
39695
39696 // a-z
39697 i$1 = 64;
39698 while (++i$1 < 91) {
39699     d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39700 }
39701
39702 function tooltip() {
39703   var tooltip = function(selection$$1) {
39704       selection$$1.each(setup);
39705     },
39706     animation = utilFunctor(false),
39707     html$$1 = utilFunctor(false),
39708     title = function() {
39709       var title = this.getAttribute('data-original-title');
39710       if (title) {
39711         return title;
39712       } else {
39713         title = this.getAttribute('title');
39714         this.removeAttribute('title');
39715         this.setAttribute('data-original-title', title);
39716       }
39717       return title;
39718     },
39719     over = 'mouseenter.tooltip',
39720     out = 'mouseleave.tooltip',
39721     placement = utilFunctor('top');
39722
39723
39724   tooltip.title = function(_) {
39725     if (arguments.length) {
39726       title = utilFunctor(_);
39727       return tooltip;
39728     } else {
39729       return title;
39730     }
39731   };
39732
39733
39734   tooltip.html = function(_) {
39735     if (arguments.length) {
39736       html$$1 = utilFunctor(_);
39737       return tooltip;
39738     } else {
39739       return html$$1;
39740     }
39741   };
39742
39743
39744   tooltip.placement = function(_) {
39745     if (arguments.length) {
39746       placement = utilFunctor(_);
39747       return tooltip;
39748     } else {
39749       return placement;
39750     }
39751   };
39752
39753
39754   tooltip.show = function(selection$$1) {
39755     selection$$1.each(show);
39756   };
39757
39758
39759   tooltip.hide = function(selection$$1) {
39760     selection$$1.each(hide);
39761   };
39762
39763
39764   tooltip.toggle = function(selection$$1) {
39765     selection$$1.each(toggle);
39766   };
39767
39768
39769   tooltip.destroy = function(selection$$1) {
39770     selection$$1
39771       .on(over, null)
39772       .on(out, null)
39773       .attr('title', function() {
39774         return this.getAttribute('data-original-title') || this.getAttribute('title');
39775       })
39776       .attr('data-original-title', null)
39777       .selectAll('.tooltip')
39778       .remove();
39779   };
39780
39781
39782   function setup() {
39783     var root = select(this),
39784         animate = animation.apply(this, arguments),
39785         tip = root.selectAll('.tooltip').data([0]);
39786
39787     var enter = tip.enter()
39788       .append('div')
39789       .attr('class', 'tooltip');
39790
39791     enter
39792       .append('div')
39793       .attr('class', 'tooltip-arrow');
39794
39795     enter
39796       .append('div')
39797       .attr('class', 'tooltip-inner');
39798
39799     tip = enter
39800       .merge(tip);
39801
39802     if (animate) {
39803       tip.classed('fade', true);
39804     }
39805
39806     var place = placement.apply(this, arguments);
39807     tip.classed(place, true);
39808
39809     root.on(over, show);
39810     root.on(out, hide);
39811   }
39812
39813
39814   function show() {
39815     var root = select(this),
39816       content = title.apply(this, arguments),
39817       tip = root.selectAll('.tooltip')
39818         .classed('in', true),
39819       markup = html$$1.apply(this, arguments);
39820
39821     tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39822     var place = placement.apply(this, arguments),
39823       outer = getPosition(root.node()),
39824       inner = getPosition(tip.node()),
39825       pos;
39826
39827     switch (place) {
39828       case 'top':
39829         pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39830         break;
39831       case 'right':
39832         pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39833         break;
39834       case 'left':
39835         pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39836         break;
39837       case 'bottom':
39838         pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39839         break;
39840     }
39841
39842     if (pos) {
39843       tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39844     } else {
39845       tip.style('left', null).style('top', null);
39846     }
39847
39848     this.tooltipVisible = true;
39849   }
39850
39851
39852   function hide() {
39853     select(this).selectAll('.tooltip')
39854       .classed('in', false);
39855
39856     this.tooltipVisible = false;
39857   }
39858
39859
39860   function toggle() {
39861     if (this.tooltipVisible) {
39862       hide.apply(this, arguments);
39863     } else {
39864       show.apply(this, arguments);
39865     }
39866   }
39867
39868   return tooltip;
39869 }
39870
39871
39872 function getPosition(node) {
39873   var mode = select(node).style('position');
39874   if (mode === 'absolute' || mode === 'static') {
39875     return {
39876       x: node.offsetLeft,
39877       y: node.offsetTop,
39878       w: node.offsetWidth,
39879       h: node.offsetHeight
39880     };
39881   } else {
39882     return {
39883       x: 0,
39884       y: 0,
39885       w: node.offsetWidth,
39886       h: node.offsetHeight
39887     };
39888   }
39889 }
39890
39891 function svgAreas$$1(projection, context) {
39892     // Patterns only work in Firefox when set directly on element.
39893     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39894     var patterns = {
39895         beach: 'beach',
39896         cemetery: 'cemetery',
39897         construction: 'construction',
39898         farm: 'farmland',
39899         farmland: 'farmland',
39900         grave_yard: 'cemetery',
39901         meadow: 'meadow',
39902         military: 'construction',
39903         orchard: 'orchard',
39904         sand: 'beach',
39905         scrub: 'scrub',
39906         wetland: 'wetland',
39907     };
39908
39909     var patternKeys = ['landuse', 'natural', 'amenity'];
39910
39911
39912     function setPattern(d) {
39913         for (var i = 0; i < patternKeys.length; i++) {
39914             if (d.tags.building && d.tags.building !== 'no') continue;
39915
39916             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39917                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39918                 return;
39919             }
39920         }
39921         this.style.fill = this.style.stroke = '';
39922     }
39923
39924
39925     return function drawAreas(selection$$1, graph, entities, filter) {
39926         var path$$1 = svgPath(projection, graph, true),
39927             areas = {},
39928             multipolygon;
39929
39930         for (var i = 0; i < entities.length; i++) {
39931             var entity = entities[i];
39932             if (entity.geometry(graph) !== 'area') continue;
39933
39934             multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
39935             if (multipolygon) {
39936                 areas[multipolygon.id] = {
39937                     entity: multipolygon.mergeTags(entity.tags),
39938                     area: Math.abs(entity.area(graph))
39939                 };
39940             } else if (!areas[entity.id]) {
39941                 areas[entity.id] = {
39942                     entity: entity,
39943                     area: Math.abs(entity.area(graph))
39944                 };
39945             }
39946         }
39947
39948         areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
39949         areas.sort(function areaSort(a, b) { return b.area - a.area; });
39950         areas = lodash.map(areas, 'entity');
39951
39952         var strokes = areas.filter(function(area$$1) {
39953             return area$$1.type === 'way';
39954         });
39955
39956         var data = {
39957             clip: areas,
39958             shadow: strokes,
39959             stroke: strokes,
39960             fill: areas
39961         };
39962
39963         var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
39964            .filter(filter)
39965            .data(data.clip, osmEntity$$1.key);
39966
39967         clipPaths.exit()
39968            .remove();
39969
39970         var clipPathsEnter = clipPaths.enter()
39971            .append('clipPath')
39972            .attr('class', 'clipPath')
39973            .attr('id', function(entity) { return entity.id + '-clippath'; });
39974
39975         clipPathsEnter
39976            .append('path');
39977
39978         clipPaths.merge(clipPathsEnter)
39979            .selectAll('path')
39980            .attr('d', path$$1);
39981
39982
39983         var layer = selection$$1.selectAll('.layer-areas');
39984
39985         var areagroup = layer
39986             .selectAll('g.areagroup')
39987             .data(['fill', 'shadow', 'stroke']);
39988
39989         areagroup = areagroup.enter()
39990             .append('g')
39991             .attr('class', function(d) { return 'areagroup area-' + d; })
39992             .merge(areagroup);
39993
39994         var paths = areagroup
39995             .selectAll('path')
39996             .filter(filter)
39997             .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
39998
39999         paths.exit()
40000             .remove();
40001
40002         var fills = selection$$1.selectAll('.area-fill path.area').nodes();
40003
40004         var bisect$$1 = bisector(function(node) {
40005             return -node.__data__.area(graph);
40006         }).left;
40007
40008         function sortedByArea(entity) {
40009             if (this._parent.__data__ === 'fill') {
40010                 return fills[bisect$$1(fills, -entity.area(graph))];
40011             }
40012         }
40013
40014         paths = paths.enter()
40015             .insert('path', sortedByArea)
40016             .merge(paths)
40017             .each(function(entity) {
40018                 var layer = this.parentNode.__data__;
40019
40020                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
40021
40022                 if (layer === 'fill') {
40023                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
40024                     setPattern.apply(this, arguments);
40025                 }
40026             })
40027             .call(svgTagClasses())
40028             .attr('d', path$$1);
40029     };
40030 }
40031
40032 function svgDebug(projection, context) {
40033
40034     function multipolygons(imagery) {
40035         return imagery.map(function(data$$1) {
40036             return {
40037                 type: 'MultiPolygon',
40038                 coordinates: [ data$$1.polygon ]
40039             };
40040         });
40041     }
40042
40043     function drawDebug(selection$$1) {
40044         var showsTile = context.getDebug('tile'),
40045             showsCollision = context.getDebug('collision'),
40046             showsImagery = context.getDebug('imagery'),
40047             showsImperial = context.getDebug('imperial'),
40048             showsDriveLeft = context.getDebug('driveLeft'),
40049             path$$1 = index$4(projection);
40050
40051
40052         var debugData = [];
40053         if (showsTile) {
40054             debugData.push({ class: 'red', label: 'tile' });
40055         }
40056         if (showsCollision) {
40057             debugData.push({ class: 'yellow', label: 'collision' });
40058         }
40059         if (showsImagery) {
40060             debugData.push({ class: 'orange', label: 'imagery' });
40061         }
40062         if (showsImperial) {
40063             debugData.push({ class: 'cyan', label: 'imperial' });
40064         }
40065         if (showsDriveLeft) {
40066             debugData.push({ class: 'green', label: 'driveLeft' });
40067         }
40068
40069
40070         var legend = select('#content')
40071             .selectAll('.debug-legend')
40072             .data(debugData.length ? [0] : []);
40073
40074         legend.exit()
40075             .remove();
40076
40077         legend = legend.enter()
40078             .append('div')
40079             .attr('class', 'fillD debug-legend')
40080             .merge(legend);
40081
40082
40083         var legendItems = legend.selectAll('.debug-legend-item')
40084             .data(debugData, function(d) { return d.label; });
40085
40086         legendItems.exit()
40087             .remove();
40088
40089         legendItems.enter()
40090             .append('span')
40091             .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
40092             .text(function(d) { return d.label; });
40093
40094
40095         var layer = selection$$1.selectAll('.layer-debug')
40096             .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
40097
40098         layer.exit()
40099             .remove();
40100
40101         layer = layer.enter()
40102             .append('g')
40103             .attr('class', 'layer-debug')
40104             .merge(layer);
40105
40106
40107         var extent$$1 = context.map().extent(),
40108             dataImagery = data.imagery || [],
40109             availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
40110                 if (!source.polygon) return false;
40111                 return source.polygon.some(function(polygon) {
40112                     return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
40113                 });
40114             }));
40115
40116         var imagery = layer.selectAll('path.debug-imagery')
40117             .data(showsImagery ? availableImagery : []);
40118
40119         imagery.exit()
40120             .remove();
40121
40122         imagery.enter()
40123             .append('path')
40124             .attr('class', 'debug-imagery debug orange');
40125
40126
40127         var imperial = layer
40128             .selectAll('path.debug-imperial')
40129             .data(showsImperial ? [dataImperial] : []);
40130
40131         imperial.exit()
40132             .remove();
40133
40134         imperial.enter()
40135             .append('path')
40136             .attr('class', 'debug-imperial debug cyan');
40137
40138
40139         var driveLeft = layer
40140             .selectAll('path.debug-drive-left')
40141             .data(showsDriveLeft ? [dataDriveLeft] : []);
40142
40143         driveLeft.exit()
40144             .remove();
40145
40146         driveLeft.enter()
40147             .append('path')
40148             .attr('class', 'debug-drive-left debug green');
40149
40150
40151         // update
40152         layer.selectAll('path')
40153             .attr('d', path$$1);
40154     }
40155
40156
40157     // This looks strange because `enabled` methods on other layers are
40158     // chainable getter/setters, and this one is just a getter.
40159     drawDebug.enabled = function() {
40160         if (!arguments.length) {
40161             return context.getDebug('tile') ||
40162                 context.getDebug('collision') ||
40163                 context.getDebug('imagery') ||
40164                 context.getDebug('imperial') ||
40165                 context.getDebug('driveLeft');
40166         } else {
40167             return this;
40168         }
40169     };
40170
40171
40172     return drawDebug;
40173 }
40174
40175 /*
40176     A standalone SVG element that contains only a `defs` sub-element. To be
40177     used once globally, since defs IDs must be unique within a document.
40178 */
40179 function svgDefs(context) {
40180
40181     function SVGSpriteDefinition(id, href) {
40182         return function(defs) {
40183             request(href)
40184                 .mimeType('image/svg+xml')
40185                 .response(function(xhr) { return xhr.responseXML; })
40186                 .get(function(err, svg) {
40187                     if (err) return;
40188                     defs.node().appendChild(
40189                         select(svg.documentElement).attr('id', id).node()
40190                     );
40191                 });
40192         };
40193     }
40194
40195
40196     return function drawDefs(selection$$1) {
40197         var defs = selection$$1.append('defs');
40198
40199         // marker
40200         defs.append('marker')
40201             .attr('id', 'oneway-marker')
40202             .attr('viewBox', '0 0 10 10')
40203             .attr('refY', 2.5)
40204             .attr('refX', 5)
40205             .attr('markerWidth', 2)
40206             .attr('markerHeight', 2)
40207             .attr('markerUnits', 'strokeWidth')
40208             .attr('orient', 'auto')
40209
40210             .append('path')
40211             .attr('class', 'oneway')
40212             .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')
40213             .attr('stroke', 'none')
40214             .attr('fill', '#000')
40215             .attr('opacity', '0.5');
40216
40217         // patterns
40218         var patterns = defs.selectAll('pattern')
40219             .data([
40220                 // pattern name, pattern image name
40221                 ['wetland', 'wetland'],
40222                 ['construction', 'construction'],
40223                 ['cemetery', 'cemetery'],
40224                 ['orchard', 'orchard'],
40225                 ['farmland', 'farmland'],
40226                 ['beach', 'dots'],
40227                 ['scrub', 'dots'],
40228                 ['meadow', 'dots']
40229             ])
40230             .enter()
40231             .append('pattern')
40232             .attr('id', function (d) {
40233                 return 'pattern-' + d[0];
40234             })
40235             .attr('width', 32)
40236             .attr('height', 32)
40237             .attr('patternUnits', 'userSpaceOnUse');
40238
40239         patterns.append('rect')
40240             .attr('x', 0)
40241             .attr('y', 0)
40242             .attr('width', 32)
40243             .attr('height', 32)
40244             .attr('class', function (d) {
40245                     return 'pattern-color-' + d[0];
40246             });
40247
40248         patterns.append('image')
40249             .attr('x', 0)
40250             .attr('y', 0)
40251             .attr('width', 32)
40252             .attr('height', 32)
40253             .attr('xlink:href', function (d) {
40254                 return context.imagePath('pattern/' + d[1] + '.png');
40255             });
40256
40257         // clip paths
40258         defs.selectAll()
40259             .data([12, 18, 20, 32, 45])
40260             .enter()
40261             .append('clipPath')
40262             .attr('id', function (d) {
40263                 return 'clip-square-' + d;
40264             })
40265             .append('rect')
40266             .attr('x', 0)
40267             .attr('y', 0)
40268             .attr('width', function (d) {
40269                 return d;
40270             })
40271             .attr('height', function (d) {
40272                 return d;
40273             });
40274
40275         defs.call(SVGSpriteDefinition(
40276             'iD-sprite',
40277             context.imagePath('iD-sprite.svg')));
40278
40279         defs.call(SVGSpriteDefinition(
40280             'maki-sprite',
40281             context.imagePath('maki-sprite.svg')));
40282     };
40283 }
40284
40285 var sax = createCommonjsModule(function (module, exports) {
40286 //[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]
40287 //[4a]          NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
40288 //[5]           Name       ::=          NameStartChar (NameChar)*
40289 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
40290 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
40291 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
40292 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
40293 //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(',')
40294
40295 //S_TAG,        S_ATTR, S_EQ,   S_V
40296 //S_ATTR_S,     S_E,    S_S,    S_C
40297 var S_TAG = 0;//tag name offerring
40298 var S_ATTR = 1;//attr name offerring 
40299 var S_ATTR_S=2;//attr name end and space offer
40300 var S_EQ = 3;//=space?
40301 var S_V = 4;//attr value(no quot value only)
40302 var S_E = 5;//attr value end and no space(quot end)
40303 var S_S = 6;//(attr value end || tag end ) && (space offer)
40304 var S_C = 7;//closed el<el />
40305
40306 function XMLReader(){
40307         
40308 }
40309
40310 XMLReader.prototype = {
40311         parse:function(source,defaultNSMap,entityMap){
40312                 var domBuilder = this.domBuilder;
40313                 domBuilder.startDocument();
40314                 _copy(defaultNSMap ,defaultNSMap = {});
40315                 parse(source,defaultNSMap,entityMap,
40316                                 domBuilder,this.errorHandler);
40317                 domBuilder.endDocument();
40318         }
40319 };
40320 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
40321   function fixedFromCharCode(code) {
40322                 // String.prototype.fromCharCode does not supports
40323                 // > 2 bytes unicode chars directly
40324                 if (code > 0xffff) {
40325                         code -= 0x10000;
40326                         var surrogate1 = 0xd800 + (code >> 10)
40327                                 , surrogate2 = 0xdc00 + (code & 0x3ff);
40328
40329                         return String.fromCharCode(surrogate1, surrogate2);
40330                 } else {
40331                         return String.fromCharCode(code);
40332                 }
40333         }
40334         function entityReplacer(a){
40335                 var k = a.slice(1,-1);
40336                 if(k in entityMap){
40337                         return entityMap[k]; 
40338                 }else if(k.charAt(0) === '#'){
40339                         return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
40340                 }else{
40341                         errorHandler.error('entity not found:'+a);
40342                         return a;
40343                 }
40344         }
40345         function appendText(end){//has some bugs
40346                 if(end>start){
40347                         var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
40348                         locator&&position(start);
40349                         domBuilder.characters(xt,0,end-start);
40350                         start = end;
40351                 }
40352         }
40353         function position(p,m){
40354                 while(p>=lineEnd && (m = linePattern.exec(source))){
40355                         lineStart = m.index;
40356                         lineEnd = lineStart + m[0].length;
40357                         locator.lineNumber++;
40358                         //console.log('line++:',locator,startPos,endPos)
40359                 }
40360                 locator.columnNumber = p-lineStart+1;
40361         }
40362         var lineStart = 0;
40363         var lineEnd = 0;
40364         var linePattern = /.+(?:\r\n?|\n)|.*$/g;
40365         var locator = domBuilder.locator;
40366         
40367         var parseStack = [{currentNSMap:defaultNSMapCopy}];
40368         var closeMap = {};
40369         var start = 0;
40370         while(true){
40371                 try{
40372                         var tagStart = source.indexOf('<',start);
40373                         if(tagStart<0){
40374                                 if(!source.substr(start).match(/^\s*$/)){
40375                                         var doc = domBuilder.document;
40376                                 var text = doc.createTextNode(source.substr(start));
40377                                 doc.appendChild(text);
40378                                 domBuilder.currentElement = text;
40379                                 }
40380                                 return;
40381                         }
40382                         if(tagStart>start){
40383                                 appendText(tagStart);
40384                         }
40385                         switch(source.charAt(tagStart+1)){
40386                         case '/':
40387                                 var end = source.indexOf('>',tagStart+3);
40388                                 var tagName = source.substring(tagStart+2,end);
40389                                 var config = parseStack.pop();
40390                                 var localNSMap = config.localNSMap;
40391                         if(config.tagName != tagName){
40392                             errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
40393                         }
40394                                 domBuilder.endElement(config.uri,config.localName,tagName);
40395                                 if(localNSMap){
40396                                         for(var prefix in localNSMap){
40397                                                 domBuilder.endPrefixMapping(prefix) ;
40398                                         }
40399                                 }
40400                                 end++;
40401                                 break;
40402                                 // end elment
40403                         case '?':// <?...?>
40404                                 locator&&position(tagStart);
40405                                 end = parseInstruction(source,tagStart,domBuilder);
40406                                 break;
40407                         case '!':// <!doctype,<![CDATA,<!--
40408                                 locator&&position(tagStart);
40409                                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
40410                                 break;
40411                         default:
40412                         
40413                                 locator&&position(tagStart);
40414                                 
40415                                 var el = new ElementAttributes();
40416                                 
40417                                 //elStartEnd
40418                                 var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
40419                                 var len = el.length;
40420                                 
40421                                 if(locator){
40422                                         if(len){
40423                                                 //attribute position fixed
40424                                                 for(var i = 0;i<len;i++){
40425                                                         var a = el[i];
40426                                                         position(a.offset);
40427                                                         a.offset = copyLocator(locator,{});
40428                                                 }
40429                                         }
40430                                         position(end);
40431                                 }
40432                                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
40433                                         el.closed = true;
40434                                         if(!entityMap.nbsp){
40435                                                 errorHandler.warning('unclosed xml attribute');
40436                                         }
40437                                 }
40438                                 appendElement(el,domBuilder,parseStack);
40439                                 
40440                                 
40441                                 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
40442                                         end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
40443                                 }else{
40444                                         end++;
40445                                 }
40446                         }
40447                 }catch(e){
40448                         errorHandler.error('element parse error: '+e);
40449                         end = -1;
40450                 }
40451                 if(end>start){
40452                         start = end;
40453                 }else{
40454                         //TODO: 这里有可能sax回退,有位置错误风险
40455                         appendText(Math.max(tagStart,start)+1);
40456                 }
40457         }
40458 }
40459 function copyLocator(f,t){
40460         t.lineNumber = f.lineNumber;
40461         t.columnNumber = f.columnNumber;
40462         return t;
40463 }
40464
40465 /**
40466  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40467  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40468  */
40469 function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
40470         var attrName;
40471         var value;
40472         var p = ++start;
40473         var s = S_TAG;//status
40474         while(true){
40475                 var c = source.charAt(p);
40476                 switch(c){
40477                 case '=':
40478                         if(s === S_ATTR){//attrName
40479                                 attrName = source.slice(start,p);
40480                                 s = S_EQ;
40481                         }else if(s === S_ATTR_S){
40482                                 s = S_EQ;
40483                         }else{
40484                                 //fatalError: equal must after attrName or space after attrName
40485                                 throw new Error('attribute equal must after attrName');
40486                         }
40487                         break;
40488                 case '\'':
40489                 case '"':
40490                         if(s === S_EQ){//equal
40491                                 start = p+1;
40492                                 p = source.indexOf(c,start);
40493                                 if(p>0){
40494                                         value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40495                                         el.add(attrName,value,start-1);
40496                                         s = S_E;
40497                                 }else{
40498                                         //fatalError: no end quot match
40499                                         throw new Error('attribute value no end \''+c+'\' match');
40500                                 }
40501                         }else if(s == S_V){
40502                                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40503                                 //console.log(attrName,value,start,p)
40504                                 el.add(attrName,value,start);
40505                                 //console.dir(el)
40506                                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40507                                 start = p+1;
40508                                 s = S_E;
40509                         }else{
40510                                 //fatalError: no equal before
40511                                 throw new Error('attribute value must after "="');
40512                         }
40513                         break;
40514                 case '/':
40515                         switch(s){
40516                         case S_TAG:
40517                                 el.setTagName(source.slice(start,p));
40518                         case S_E:
40519                         case S_S:
40520                         case S_C:
40521                                 s = S_C;
40522                                 el.closed = true;
40523                         case S_V:
40524                         case S_ATTR:
40525                         case S_ATTR_S:
40526                                 break;
40527                         //case S_EQ:
40528                         default:
40529                                 throw new Error("attribute invalid close char('/')")
40530                         }
40531                         break;
40532                 case ''://end document
40533                         //throw new Error('unexpected end of input')
40534                         errorHandler.error('unexpected end of input');
40535                 case '>':
40536                         switch(s){
40537                         case S_TAG:
40538                                 el.setTagName(source.slice(start,p));
40539                         case S_E:
40540                         case S_S:
40541                         case S_C:
40542                                 break;//normal
40543                         case S_V://Compatible state
40544                         case S_ATTR:
40545                                 value = source.slice(start,p);
40546                                 if(value.slice(-1) === '/'){
40547                                         el.closed  = true;
40548                                         value = value.slice(0,-1);
40549                                 }
40550                         case S_ATTR_S:
40551                                 if(s === S_ATTR_S){
40552                                         value = attrName;
40553                                 }
40554                                 if(s == S_V){
40555                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40556                                         el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40557                                 }else{
40558                                         errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40559                                         el.add(value,value,start);
40560                                 }
40561                                 break;
40562                         case S_EQ:
40563                                 throw new Error('attribute value missed!!');
40564                         }
40565 //                      console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40566                         return p;
40567                 /*xml space '\x20' | #x9 | #xD | #xA; */
40568                 case '\u0080':
40569                         c = ' ';
40570                 default:
40571                         if(c<= ' '){//space
40572                                 switch(s){
40573                                 case S_TAG:
40574                                         el.setTagName(source.slice(start,p));//tagName
40575                                         s = S_S;
40576                                         break;
40577                                 case S_ATTR:
40578                                         attrName = source.slice(start,p);
40579                                         s = S_ATTR_S;
40580                                         break;
40581                                 case S_V:
40582                                         var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40583                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40584                                         el.add(attrName,value,start);
40585                                 case S_E:
40586                                         s = S_S;
40587                                         break;
40588                                 //case S_S:
40589                                 //case S_EQ:
40590                                 //case S_ATTR_S:
40591                                 //      void();break;
40592                                 //case S_C:
40593                                         //ignore warning
40594                                 }
40595                         }else{//not space
40596 //S_TAG,        S_ATTR, S_EQ,   S_V
40597 //S_ATTR_S,     S_E,    S_S,    S_C
40598                                 switch(s){
40599                                 //case S_TAG:void();break;
40600                                 //case S_ATTR:void();break;
40601                                 //case S_V:void();break;
40602                                 case S_ATTR_S:
40603                                         errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!');
40604                                         el.add(attrName,attrName,start);
40605                                         start = p;
40606                                         s = S_ATTR;
40607                                         break;
40608                                 case S_E:
40609                                         errorHandler.warning('attribute space is required"'+attrName+'"!!');
40610                                 case S_S:
40611                                         s = S_ATTR;
40612                                         start = p;
40613                                         break;
40614                                 case S_EQ:
40615                                         s = S_V;
40616                                         start = p;
40617                                         break;
40618                                 case S_C:
40619                                         throw new Error("elements closed character '/' and '>' must be connected to");
40620                                 }
40621                         }
40622                 }
40623                 p++;
40624         }
40625 }
40626 /**
40627  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40628  */
40629 function appendElement(el,domBuilder,parseStack){
40630         var tagName = el.tagName;
40631         var localNSMap = null;
40632         var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40633         var i = el.length;
40634         while(i--){
40635                 var a = el[i];
40636                 var qName = a.qName;
40637                 var value = a.value;
40638                 var nsp = qName.indexOf(':');
40639                 if(nsp>0){
40640                         var prefix = a.prefix = qName.slice(0,nsp);
40641                         var localName = qName.slice(nsp+1);
40642                         var nsPrefix = prefix === 'xmlns' && localName;
40643                 }else{
40644                         localName = qName;
40645                         prefix = null;
40646                         nsPrefix = qName === 'xmlns' && '';
40647                 }
40648                 //can not set prefix,because prefix !== ''
40649                 a.localName = localName ;
40650                 //prefix == null for no ns prefix attribute 
40651                 if(nsPrefix !== false){//hack!!
40652                         if(localNSMap == null){
40653                                 localNSMap = {};
40654                                 //console.log(currentNSMap,0)
40655                                 _copy(currentNSMap,currentNSMap={});
40656                                 //console.log(currentNSMap,1)
40657                         }
40658                         currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40659                         a.uri = 'http://www.w3.org/2000/xmlns/';
40660                         domBuilder.startPrefixMapping(nsPrefix, value); 
40661                 }
40662         }
40663         var i = el.length;
40664         while(i--){
40665                 a = el[i];
40666                 var prefix = a.prefix;
40667                 if(prefix){//no prefix attribute has no namespace
40668                         if(prefix === 'xml'){
40669                                 a.uri = 'http://www.w3.org/XML/1998/namespace';
40670                         }if(prefix !== 'xmlns'){
40671                                 a.uri = currentNSMap[prefix];
40672                                 
40673                                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40674                         }
40675                 }
40676         }
40677         var nsp = tagName.indexOf(':');
40678         if(nsp>0){
40679                 prefix = el.prefix = tagName.slice(0,nsp);
40680                 localName = el.localName = tagName.slice(nsp+1);
40681         }else{
40682                 prefix = null;//important!!
40683                 localName = el.localName = tagName;
40684         }
40685         //no prefix element has default namespace
40686         var ns = el.uri = currentNSMap[prefix || ''];
40687         domBuilder.startElement(ns,localName,tagName,el);
40688         //endPrefixMapping and startPrefixMapping have not any help for dom builder
40689         //localNSMap = null
40690         if(el.closed){
40691                 domBuilder.endElement(ns,localName,tagName);
40692                 if(localNSMap){
40693                         for(prefix in localNSMap){
40694                                 domBuilder.endPrefixMapping(prefix); 
40695                         }
40696                 }
40697         }else{
40698                 el.currentNSMap = currentNSMap;
40699                 el.localNSMap = localNSMap;
40700                 parseStack.push(el);
40701         }
40702 }
40703 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40704         if(/^(?:script|textarea)$/i.test(tagName)){
40705                 var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
40706                 var text = source.substring(elStartEnd+1,elEndStart);
40707                 if(/[&<]/.test(text)){
40708                         if(/^script$/i.test(tagName)){
40709                                 //if(!/\]\]>/.test(text)){
40710                                         //lexHandler.startCDATA();
40711                                         domBuilder.characters(text,0,text.length);
40712                                         //lexHandler.endCDATA();
40713                                         return elEndStart;
40714                                 //}
40715                         }//}else{//text area
40716                                 text = text.replace(/&#?\w+;/g,entityReplacer);
40717                                 domBuilder.characters(text,0,text.length);
40718                                 return elEndStart;
40719                         //}
40720                         
40721                 }
40722         }
40723         return elStartEnd+1;
40724 }
40725 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40726         //if(tagName in closeMap){
40727         var pos = closeMap[tagName];
40728         if(pos == null){
40729                 //console.log(tagName)
40730                 pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>');
40731         }
40732         return pos<elStartEnd;
40733         //} 
40734 }
40735 function _copy(source,target){
40736         for(var n in source){target[n] = source[n];}
40737 }
40738 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40739         var next= source.charAt(start+2);
40740         switch(next){
40741         case '-':
40742                 if(source.charAt(start + 3) === '-'){
40743                         var end = source.indexOf('-->',start+4);
40744                         //append comment source.substring(4,end)//<!--
40745                         if(end>start){
40746                                 domBuilder.comment(source,start+4,end-start-4);
40747                                 return end+3;
40748                         }else{
40749                                 errorHandler.error("Unclosed comment");
40750                                 return -1;
40751                         }
40752                 }else{
40753                         //error
40754                         return -1;
40755                 }
40756         default:
40757                 if(source.substr(start+3,6) == 'CDATA['){
40758                         var end = source.indexOf(']]>',start+9);
40759                         domBuilder.startCDATA();
40760                         domBuilder.characters(source,start+9,end-start-9);
40761                         domBuilder.endCDATA(); 
40762                         return end+3;
40763                 }
40764                 //<!DOCTYPE
40765                 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
40766                 var matchs = split(source,start);
40767                 var len = matchs.length;
40768                 if(len>1 && /!doctype/i.test(matchs[0][0])){
40769                         var name = matchs[1][0];
40770                         var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40771                         var sysid = len>4 && matchs[4][0];
40772                         var lastMatch = matchs[len-1];
40773                         domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40774                                         sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40775                         domBuilder.endDTD();
40776                         
40777                         return lastMatch.index+lastMatch[0].length
40778                 }
40779         }
40780         return -1;
40781 }
40782
40783
40784
40785 function parseInstruction(source,start,domBuilder){
40786         var end = source.indexOf('?>',start);
40787         if(end){
40788                 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40789                 if(match){
40790                         var len = match[0].length;
40791                         domBuilder.processingInstruction(match[1], match[2]) ;
40792                         return end+2;
40793                 }else{//error
40794                         return -1;
40795                 }
40796         }
40797         return -1;
40798 }
40799
40800 /**
40801  * @param source
40802  */
40803 function ElementAttributes(source){
40804         
40805 }
40806 ElementAttributes.prototype = {
40807         setTagName:function(tagName){
40808                 if(!tagNamePattern.test(tagName)){
40809                         throw new Error('invalid tagName:'+tagName)
40810                 }
40811                 this.tagName = tagName;
40812         },
40813         add:function(qName,value,offset){
40814                 if(!tagNamePattern.test(qName)){
40815                         throw new Error('invalid attribute:'+qName)
40816                 }
40817                 this[this.length++] = {qName:qName,value:value,offset:offset};
40818         },
40819         length:0,
40820         getLocalName:function(i){return this[i].localName},
40821         getOffset:function(i){return this[i].offset},
40822         getQName:function(i){return this[i].qName},
40823         getURI:function(i){return this[i].uri},
40824         getValue:function(i){return this[i].value}
40825 //      ,getIndex:function(uri, localName)){
40826 //              if(localName){
40827 //                      
40828 //              }else{
40829 //                      var qName = uri
40830 //              }
40831 //      },
40832 //      getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40833 //      getType:function(uri,localName){}
40834 //      getType:function(i){},
40835 };
40836
40837
40838
40839
40840 function _set_proto_(thiz,parent){
40841         thiz.__proto__ = parent;
40842         return thiz;
40843 }
40844 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40845         _set_proto_ = function(thiz,parent){
40846                 function p(){}
40847                 p.prototype = parent;
40848                 p = new p();
40849                 for(parent in thiz){
40850                         p[parent] = thiz[parent];
40851                 }
40852                 return p;
40853         };
40854 }
40855
40856 function split(source,start){
40857         var match;
40858         var buf = [];
40859         var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40860         reg.lastIndex = start;
40861         reg.exec(source);//skip <
40862         while(match = reg.exec(source)){
40863                 buf.push(match);
40864                 if(match[1])return buf;
40865         }
40866 }
40867
40868 if(typeof commonjsRequire == 'function'){
40869         exports.XMLReader = XMLReader;
40870 }
40871 });
40872
40873 var dom = createCommonjsModule(function (module, exports) {
40874 /*
40875  * DOM Level 2
40876  * Object DOMException
40877  * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40878  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40879  */
40880
40881 function copy(src,dest){
40882         for(var p in src){
40883                 dest[p] = src[p];
40884         }
40885 }
40886 /**
40887 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
40888 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
40889  */
40890 function _extends(Class,Super){
40891         var pt = Class.prototype;
40892         if(Object.create){
40893                 var ppt = Object.create(Super.prototype);
40894                 pt.__proto__ = ppt;
40895         }
40896         if(!(pt instanceof Super)){
40897                 function t(){}
40898                 t.prototype = Super.prototype;
40899                 t = new t();
40900                 copy(pt,t);
40901                 Class.prototype = pt = t;
40902         }
40903         if(pt.constructor != Class){
40904                 if(typeof Class != 'function'){
40905                         console.error("unknow Class:"+Class);
40906                 }
40907                 pt.constructor = Class;
40908         }
40909 }
40910 var htmlns = 'http://www.w3.org/1999/xhtml';
40911 // Node Types
40912 var NodeType = {};
40913 var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
40914 var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
40915 var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
40916 var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
40917 var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
40918 var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
40919 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
40920 var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
40921 var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
40922 var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
40923 var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
40924 var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;
40925
40926 // ExceptionCode
40927 var ExceptionCode = {};
40928 var ExceptionMessage = {};
40929 var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
40930 var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
40931 var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
40932 var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
40933 var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
40934 var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
40935 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
40936 var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
40937 var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
40938 var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
40939 //level2
40940 var INVALID_STATE_ERR           = ExceptionCode.INVALID_STATE_ERR               = ((ExceptionMessage[11]="Invalid state"),11);
40941 var SYNTAX_ERR                  = ExceptionCode.SYNTAX_ERR                      = ((ExceptionMessage[12]="Syntax error"),12);
40942 var INVALID_MODIFICATION_ERR    = ExceptionCode.INVALID_MODIFICATION_ERR        = ((ExceptionMessage[13]="Invalid modification"),13);
40943 var NAMESPACE_ERR               = ExceptionCode.NAMESPACE_ERR                   = ((ExceptionMessage[14]="Invalid namespace"),14);
40944 var INVALID_ACCESS_ERR          = ExceptionCode.INVALID_ACCESS_ERR              = ((ExceptionMessage[15]="Invalid access"),15);
40945
40946
40947 function DOMException(code, message) {
40948         if(message instanceof Error){
40949                 var error = message;
40950         }else{
40951                 error = this;
40952                 Error.call(this, ExceptionMessage[code]);
40953                 this.message = ExceptionMessage[code];
40954                 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
40955         }
40956         error.code = code;
40957         if(message) this.message = this.message + ": " + message;
40958         return error;
40959 }
40960 DOMException.prototype = Error.prototype;
40961 copy(ExceptionCode,DOMException);
40962 /**
40963  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
40964  * 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.
40965  * The items in the NodeList are accessible via an integral index, starting from 0.
40966  */
40967 function NodeList() {
40968 }
40969 NodeList.prototype = {
40970         /**
40971          * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
40972          * @standard level1
40973          */
40974         length:0, 
40975         /**
40976          * 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.
40977          * @standard level1
40978          * @param index  unsigned long 
40979          *   Index into the collection.
40980          * @return Node
40981          *      The node at the indexth position in the NodeList, or null if that is not a valid index. 
40982          */
40983         item: function(index) {
40984                 return this[index] || null;
40985         },
40986         toString:function(){
40987                 for(var buf = [], i = 0;i<this.length;i++){
40988                         serializeToString(this[i],buf);
40989                 }
40990                 return buf.join('');
40991         }
40992 };
40993 function LiveNodeList(node,refresh){
40994         this._node = node;
40995         this._refresh = refresh;
40996         _updateLiveList(this);
40997 }
40998 function _updateLiveList(list){
40999         var inc = list._node._inc || list._node.ownerDocument._inc;
41000         if(list._inc != inc){
41001                 var ls = list._refresh(list._node);
41002                 //console.log(ls.length)
41003                 __set__(list,'length',ls.length);
41004                 copy(ls,list);
41005                 list._inc = inc;
41006         }
41007 }
41008 LiveNodeList.prototype.item = function(i){
41009         _updateLiveList(this);
41010         return this[i];
41011 };
41012
41013 _extends(LiveNodeList,NodeList);
41014 /**
41015  * 
41016  * 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.
41017  * NamedNodeMap objects in the DOM are live.
41018  * used for attributes or DocumentType entities 
41019  */
41020 function NamedNodeMap() {
41021 }
41022
41023 function _findNodeIndex(list,node){
41024         var i = list.length;
41025         while(i--){
41026                 if(list[i] === node){return i}
41027         }
41028 }
41029
41030 function _addNamedNode(el,list,newAttr,oldAttr){
41031         if(oldAttr){
41032                 list[_findNodeIndex(list,oldAttr)] = newAttr;
41033         }else{
41034                 list[list.length++] = newAttr;
41035         }
41036         if(el){
41037                 newAttr.ownerElement = el;
41038                 var doc = el.ownerDocument;
41039                 if(doc){
41040                         oldAttr && _onRemoveAttribute(doc,el,oldAttr);
41041                         _onAddAttribute(doc,el,newAttr);
41042                 }
41043         }
41044 }
41045 function _removeNamedNode(el,list,attr){
41046         var i = _findNodeIndex(list,attr);
41047         if(i>=0){
41048                 var lastIndex = list.length-1;
41049                 while(i<lastIndex){
41050                         list[i] = list[++i];
41051                 }
41052                 list.length = lastIndex;
41053                 if(el){
41054                         var doc = el.ownerDocument;
41055                         if(doc){
41056                                 _onRemoveAttribute(doc,el,attr);
41057                                 attr.ownerElement = null;
41058                         }
41059                 }
41060         }else{
41061                 throw DOMException(NOT_FOUND_ERR,new Error())
41062         }
41063 }
41064 NamedNodeMap.prototype = {
41065         length:0,
41066         item:NodeList.prototype.item,
41067         getNamedItem: function(key) {
41068 //              if(key.indexOf(':')>0 || key == 'xmlns'){
41069 //                      return null;
41070 //              }
41071                 var i = this.length;
41072                 while(i--){
41073                         var attr = this[i];
41074                         if(attr.nodeName == key){
41075                                 return attr;
41076                         }
41077                 }
41078         },
41079         setNamedItem: function(attr) {
41080                 var el = attr.ownerElement;
41081                 if(el && el!=this._ownerElement){
41082                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
41083                 }
41084                 var oldAttr = this.getNamedItem(attr.nodeName);
41085                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41086                 return oldAttr;
41087         },
41088         /* returns Node */
41089         setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
41090                 var el = attr.ownerElement, oldAttr;
41091                 if(el && el!=this._ownerElement){
41092                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
41093                 }
41094                 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
41095                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
41096                 return oldAttr;
41097         },
41098
41099         /* returns Node */
41100         removeNamedItem: function(key) {
41101                 var attr = this.getNamedItem(key);
41102                 _removeNamedNode(this._ownerElement,this,attr);
41103                 return attr;
41104                 
41105                 
41106         },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
41107         
41108         //for level2
41109         removeNamedItemNS:function(namespaceURI,localName){
41110                 var attr = this.getNamedItemNS(namespaceURI,localName);
41111                 _removeNamedNode(this._ownerElement,this,attr);
41112                 return attr;
41113         },
41114         getNamedItemNS: function(namespaceURI, localName) {
41115                 var i = this.length;
41116                 while(i--){
41117                         var node = this[i];
41118                         if(node.localName == localName && node.namespaceURI == namespaceURI){
41119                                 return node;
41120                         }
41121                 }
41122                 return null;
41123         }
41124 };
41125 /**
41126  * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
41127  */
41128 function DOMImplementation(/* Object */ features) {
41129         this._features = {};
41130         if (features) {
41131                 for (var feature in features) {
41132                          this._features = features[feature];
41133                 }
41134         }
41135 }
41136
41137 DOMImplementation.prototype = {
41138         hasFeature: function(/* string */ feature, /* string */ version) {
41139                 var versions = this._features[feature.toLowerCase()];
41140                 if (versions && (!version || version in versions)) {
41141                         return true;
41142                 } else {
41143                         return false;
41144                 }
41145         },
41146         // Introduced in DOM Level 2:
41147         createDocument:function(namespaceURI,  qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
41148                 var doc = new Document();
41149                 doc.implementation = this;
41150                 doc.childNodes = new NodeList();
41151                 doc.doctype = doctype;
41152                 if(doctype){
41153                         doc.appendChild(doctype);
41154                 }
41155                 if(qualifiedName){
41156                         var root = doc.createElementNS(namespaceURI,qualifiedName);
41157                         doc.appendChild(root);
41158                 }
41159                 return doc;
41160         },
41161         // Introduced in DOM Level 2:
41162         createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
41163                 var node = new DocumentType();
41164                 node.name = qualifiedName;
41165                 node.nodeName = qualifiedName;
41166                 node.publicId = publicId;
41167                 node.systemId = systemId;
41168                 // Introduced in DOM Level 2:
41169                 //readonly attribute DOMString        internalSubset;
41170                 
41171                 //TODO:..
41172                 //  readonly attribute NamedNodeMap     entities;
41173                 //  readonly attribute NamedNodeMap     notations;
41174                 return node;
41175         }
41176 };
41177
41178
41179 /**
41180  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
41181  */
41182
41183 function Node() {
41184 }
41185
41186 Node.prototype = {
41187         firstChild : null,
41188         lastChild : null,
41189         previousSibling : null,
41190         nextSibling : null,
41191         attributes : null,
41192         parentNode : null,
41193         childNodes : null,
41194         ownerDocument : null,
41195         nodeValue : null,
41196         namespaceURI : null,
41197         prefix : null,
41198         localName : null,
41199         // Modified in DOM Level 2:
41200         insertBefore:function(newChild, refChild){//raises 
41201                 return _insertBefore(this,newChild,refChild);
41202         },
41203         replaceChild:function(newChild, oldChild){//raises 
41204                 this.insertBefore(newChild,oldChild);
41205                 if(oldChild){
41206                         this.removeChild(oldChild);
41207                 }
41208         },
41209         removeChild:function(oldChild){
41210                 return _removeChild(this,oldChild);
41211         },
41212         appendChild:function(newChild){
41213                 return this.insertBefore(newChild,null);
41214         },
41215         hasChildNodes:function(){
41216                 return this.firstChild != null;
41217         },
41218         cloneNode:function(deep){
41219                 return cloneNode(this.ownerDocument||this,this,deep);
41220         },
41221         // Modified in DOM Level 2:
41222         normalize:function(){
41223                 var child = this.firstChild;
41224                 while(child){
41225                         var next = child.nextSibling;
41226                         if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
41227                                 this.removeChild(next);
41228                                 child.appendData(next.data);
41229                         }else{
41230                                 child.normalize();
41231                                 child = next;
41232                         }
41233                 }
41234         },
41235         // Introduced in DOM Level 2:
41236         isSupported:function(feature, version){
41237                 return this.ownerDocument.implementation.hasFeature(feature,version);
41238         },
41239     // Introduced in DOM Level 2:
41240     hasAttributes:function(){
41241         return this.attributes.length>0;
41242     },
41243     lookupPrefix:function(namespaceURI){
41244         var el = this;
41245         while(el){
41246                 var map = el._nsMap;
41247                 //console.dir(map)
41248                 if(map){
41249                         for(var n in map){
41250                                 if(map[n] == namespaceURI){
41251                                         return n;
41252                                 }
41253                         }
41254                 }
41255                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41256         }
41257         return null;
41258     },
41259     // Introduced in DOM Level 3:
41260     lookupNamespaceURI:function(prefix){
41261         var el = this;
41262         while(el){
41263                 var map = el._nsMap;
41264                 //console.dir(map)
41265                 if(map){
41266                         if(prefix in map){
41267                                 return map[prefix] ;
41268                         }
41269                 }
41270                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
41271         }
41272         return null;
41273     },
41274     // Introduced in DOM Level 3:
41275     isDefaultNamespace:function(namespaceURI){
41276         var prefix = this.lookupPrefix(namespaceURI);
41277         return prefix == null;
41278     }
41279 };
41280
41281
41282 function _xmlEncoder(c){
41283         return c == '<' && '&lt;' ||
41284          c == '>' && '&gt;' ||
41285          c == '&' && '&amp;' ||
41286          c == '"' && '&quot;' ||
41287          '&#'+c.charCodeAt()+';'
41288 }
41289
41290
41291 copy(NodeType,Node);
41292 copy(NodeType,Node.prototype);
41293
41294 /**
41295  * @param callback return true for continue,false for break
41296  * @return boolean true: break visit;
41297  */
41298 function _visitNode(node,callback){
41299         if(callback(node)){
41300                 return true;
41301         }
41302         if(node = node.firstChild){
41303                 do{
41304                         if(_visitNode(node,callback)){return true}
41305         }while(node=node.nextSibling)
41306     }
41307 }
41308
41309
41310
41311 function Document(){
41312 }
41313 function _onAddAttribute(doc,el,newAttr){
41314         doc && doc._inc++;
41315         var ns = newAttr.namespaceURI;
41316         if(ns == 'http://www.w3.org/2000/xmlns/'){
41317                 //update namespace
41318                 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
41319         }
41320 }
41321 function _onRemoveAttribute(doc,el,newAttr,remove){
41322         doc && doc._inc++;
41323         var ns = newAttr.namespaceURI;
41324         if(ns == 'http://www.w3.org/2000/xmlns/'){
41325                 //update namespace
41326                 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
41327         }
41328 }
41329 function _onUpdateChild(doc,el,newChild){
41330         if(doc && doc._inc){
41331                 doc._inc++;
41332                 //update childNodes
41333                 var cs = el.childNodes;
41334                 if(newChild){
41335                         cs[cs.length++] = newChild;
41336                 }else{
41337                         //console.log(1)
41338                         var child = el.firstChild;
41339                         var i = 0;
41340                         while(child){
41341                                 cs[i++] = child;
41342                                 child =child.nextSibling;
41343                         }
41344                         cs.length = i;
41345                 }
41346         }
41347 }
41348
41349 /**
41350  * attributes;
41351  * children;
41352  * 
41353  * writeable properties:
41354  * nodeValue,Attr:value,CharacterData:data
41355  * prefix
41356  */
41357 function _removeChild(parentNode,child){
41358         var previous = child.previousSibling;
41359         var next = child.nextSibling;
41360         if(previous){
41361                 previous.nextSibling = next;
41362         }else{
41363                 parentNode.firstChild = next;
41364         }
41365         if(next){
41366                 next.previousSibling = previous;
41367         }else{
41368                 parentNode.lastChild = previous;
41369         }
41370         _onUpdateChild(parentNode.ownerDocument,parentNode);
41371         return child;
41372 }
41373 /**
41374  * preformance key(refChild == null)
41375  */
41376 function _insertBefore(parentNode,newChild,nextChild){
41377         var cp = newChild.parentNode;
41378         if(cp){
41379                 cp.removeChild(newChild);//remove and update
41380         }
41381         if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41382                 var newFirst = newChild.firstChild;
41383                 if (newFirst == null) {
41384                         return newChild;
41385                 }
41386                 var newLast = newChild.lastChild;
41387         }else{
41388                 newFirst = newLast = newChild;
41389         }
41390         var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
41391
41392         newFirst.previousSibling = pre;
41393         newLast.nextSibling = nextChild;
41394         
41395         
41396         if(pre){
41397                 pre.nextSibling = newFirst;
41398         }else{
41399                 parentNode.firstChild = newFirst;
41400         }
41401         if(nextChild == null){
41402                 parentNode.lastChild = newLast;
41403         }else{
41404                 nextChild.previousSibling = newLast;
41405         }
41406         do{
41407                 newFirst.parentNode = parentNode;
41408         }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
41409         _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
41410         //console.log(parentNode.lastChild.nextSibling == null)
41411         if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
41412                 newChild.firstChild = newChild.lastChild = null;
41413         }
41414         return newChild;
41415 }
41416 function _appendSingleChild(parentNode,newChild){
41417         var cp = newChild.parentNode;
41418         if(cp){
41419                 var pre = parentNode.lastChild;
41420                 cp.removeChild(newChild);//remove and update
41421                 var pre = parentNode.lastChild;
41422         }
41423         var pre = parentNode.lastChild;
41424         newChild.parentNode = parentNode;
41425         newChild.previousSibling = pre;
41426         newChild.nextSibling = null;
41427         if(pre){
41428                 pre.nextSibling = newChild;
41429         }else{
41430                 parentNode.firstChild = newChild;
41431         }
41432         parentNode.lastChild = newChild;
41433         _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
41434         return newChild;
41435         //console.log("__aa",parentNode.lastChild.nextSibling == null)
41436 }
41437 Document.prototype = {
41438         //implementation : null,
41439         nodeName :  '#document',
41440         nodeType :  DOCUMENT_NODE,
41441         doctype :  null,
41442         documentElement :  null,
41443         _inc : 1,
41444         
41445         insertBefore :  function(newChild, refChild){//raises 
41446                 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
41447                         var child = newChild.firstChild;
41448                         while(child){
41449                                 var next = child.nextSibling;
41450                                 this.insertBefore(child,refChild);
41451                                 child = next;
41452                         }
41453                         return newChild;
41454                 }
41455                 if(this.documentElement == null && newChild.nodeType == 1){
41456                         this.documentElement = newChild;
41457                 }
41458                 
41459                 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41460         },
41461         removeChild :  function(oldChild){
41462                 if(this.documentElement == oldChild){
41463                         this.documentElement = null;
41464                 }
41465                 return _removeChild(this,oldChild);
41466         },
41467         // Introduced in DOM Level 2:
41468         importNode : function(importedNode,deep){
41469                 return importNode(this,importedNode,deep);
41470         },
41471         // Introduced in DOM Level 2:
41472         getElementById :        function(id){
41473                 var rtv = null;
41474                 _visitNode(this.documentElement,function(node){
41475                         if(node.nodeType == 1){
41476                                 if(node.getAttribute('id') == id){
41477                                         rtv = node;
41478                                         return true;
41479                                 }
41480                         }
41481                 });
41482                 return rtv;
41483         },
41484         
41485         //document factory method:
41486         createElement : function(tagName){
41487                 var node = new Element();
41488                 node.ownerDocument = this;
41489                 node.nodeName = tagName;
41490                 node.tagName = tagName;
41491                 node.childNodes = new NodeList();
41492                 var attrs       = node.attributes = new NamedNodeMap();
41493                 attrs._ownerElement = node;
41494                 return node;
41495         },
41496         createDocumentFragment :        function(){
41497                 var node = new DocumentFragment();
41498                 node.ownerDocument = this;
41499                 node.childNodes = new NodeList();
41500                 return node;
41501         },
41502         createTextNode :        function(data){
41503                 var node = new Text();
41504                 node.ownerDocument = this;
41505                 node.appendData(data);
41506                 return node;
41507         },
41508         createComment : function(data){
41509                 var node = new Comment();
41510                 node.ownerDocument = this;
41511                 node.appendData(data);
41512                 return node;
41513         },
41514         createCDATASection :    function(data){
41515                 var node = new CDATASection();
41516                 node.ownerDocument = this;
41517                 node.appendData(data);
41518                 return node;
41519         },
41520         createProcessingInstruction :   function(target,data){
41521                 var node = new ProcessingInstruction();
41522                 node.ownerDocument = this;
41523                 node.tagName = node.target = target;
41524                 node.nodeValue= node.data = data;
41525                 return node;
41526         },
41527         createAttribute :       function(name){
41528                 var node = new Attr();
41529                 node.ownerDocument      = this;
41530                 node.name = name;
41531                 node.nodeName   = name;
41532                 node.localName = name;
41533                 node.specified = true;
41534                 return node;
41535         },
41536         createEntityReference : function(name){
41537                 var node = new EntityReference();
41538                 node.ownerDocument      = this;
41539                 node.nodeName   = name;
41540                 return node;
41541         },
41542         // Introduced in DOM Level 2:
41543         createElementNS :       function(namespaceURI,qualifiedName){
41544                 var node = new Element();
41545                 var pl = qualifiedName.split(':');
41546                 var attrs       = node.attributes = new NamedNodeMap();
41547                 node.childNodes = new NodeList();
41548                 node.ownerDocument = this;
41549                 node.nodeName = qualifiedName;
41550                 node.tagName = qualifiedName;
41551                 node.namespaceURI = namespaceURI;
41552                 if(pl.length == 2){
41553                         node.prefix = pl[0];
41554                         node.localName = pl[1];
41555                 }else{
41556                         //el.prefix = null;
41557                         node.localName = qualifiedName;
41558                 }
41559                 attrs._ownerElement = node;
41560                 return node;
41561         },
41562         // Introduced in DOM Level 2:
41563         createAttributeNS :     function(namespaceURI,qualifiedName){
41564                 var node = new Attr();
41565                 var pl = qualifiedName.split(':');
41566                 node.ownerDocument = this;
41567                 node.nodeName = qualifiedName;
41568                 node.name = qualifiedName;
41569                 node.namespaceURI = namespaceURI;
41570                 node.specified = true;
41571                 if(pl.length == 2){
41572                         node.prefix = pl[0];
41573                         node.localName = pl[1];
41574                 }else{
41575                         //el.prefix = null;
41576                         node.localName = qualifiedName;
41577                 }
41578                 return node;
41579         }
41580 };
41581 _extends(Document,Node);
41582
41583
41584 function Element() {
41585         this._nsMap = {};
41586 }
41587 Element.prototype = {
41588         nodeType : ELEMENT_NODE,
41589         hasAttribute : function(name){
41590                 return this.getAttributeNode(name)!=null;
41591         },
41592         getAttribute : function(name){
41593                 var attr = this.getAttributeNode(name);
41594                 return attr && attr.value || '';
41595         },
41596         getAttributeNode : function(name){
41597                 return this.attributes.getNamedItem(name);
41598         },
41599         setAttribute : function(name, value){
41600                 var attr = this.ownerDocument.createAttribute(name);
41601                 attr.value = attr.nodeValue = "" + value;
41602                 this.setAttributeNode(attr);
41603         },
41604         removeAttribute : function(name){
41605                 var attr = this.getAttributeNode(name);
41606                 attr && this.removeAttributeNode(attr);
41607         },
41608         
41609         //four real opeartion method
41610         appendChild:function(newChild){
41611                 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41612                         return this.insertBefore(newChild,null);
41613                 }else{
41614                         return _appendSingleChild(this,newChild);
41615                 }
41616         },
41617         setAttributeNode : function(newAttr){
41618                 return this.attributes.setNamedItem(newAttr);
41619         },
41620         setAttributeNodeNS : function(newAttr){
41621                 return this.attributes.setNamedItemNS(newAttr);
41622         },
41623         removeAttributeNode : function(oldAttr){
41624                 return this.attributes.removeNamedItem(oldAttr.nodeName);
41625         },
41626         //get real attribute name,and remove it by removeAttributeNode
41627         removeAttributeNS : function(namespaceURI, localName){
41628                 var old = this.getAttributeNodeNS(namespaceURI, localName);
41629                 old && this.removeAttributeNode(old);
41630         },
41631         
41632         hasAttributeNS : function(namespaceURI, localName){
41633                 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41634         },
41635         getAttributeNS : function(namespaceURI, localName){
41636                 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41637                 return attr && attr.value || '';
41638         },
41639         setAttributeNS : function(namespaceURI, qualifiedName, value){
41640                 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41641                 attr.value = attr.nodeValue = "" + value;
41642                 this.setAttributeNode(attr);
41643         },
41644         getAttributeNodeNS : function(namespaceURI, localName){
41645                 return this.attributes.getNamedItemNS(namespaceURI, localName);
41646         },
41647         
41648         getElementsByTagName : function(tagName){
41649                 return new LiveNodeList(this,function(base){
41650                         var ls = [];
41651                         _visitNode(base,function(node){
41652                                 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41653                                         ls.push(node);
41654                                 }
41655                         });
41656                         return ls;
41657                 });
41658         },
41659         getElementsByTagNameNS : function(namespaceURI, localName){
41660                 return new LiveNodeList(this,function(base){
41661                         var ls = [];
41662                         _visitNode(base,function(node){
41663                                 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41664                                         ls.push(node);
41665                                 }
41666                         });
41667                         return ls;
41668                 });
41669         }
41670 };
41671 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41672 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41673
41674
41675 _extends(Element,Node);
41676 function Attr() {
41677 }
41678 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41679 _extends(Attr,Node);
41680
41681
41682 function CharacterData() {
41683 }
41684 CharacterData.prototype = {
41685         data : '',
41686         substringData : function(offset, count) {
41687                 return this.data.substring(offset, offset+count);
41688         },
41689         appendData: function(text) {
41690                 text = this.data+text;
41691                 this.nodeValue = this.data = text;
41692                 this.length = text.length;
41693         },
41694         insertData: function(offset,text) {
41695                 this.replaceData(offset,0,text);
41696         
41697         },
41698         appendChild:function(newChild){
41699                 //if(!(newChild instanceof CharacterData)){
41700                         throw new Error(ExceptionMessage[3])
41701                 //}
41702                 return Node.prototype.appendChild.apply(this,arguments)
41703         },
41704         deleteData: function(offset, count) {
41705                 this.replaceData(offset,count,"");
41706         },
41707         replaceData: function(offset, count, text) {
41708                 var start = this.data.substring(0,offset);
41709                 var end = this.data.substring(offset+count);
41710                 text = start + text + end;
41711                 this.nodeValue = this.data = text;
41712                 this.length = text.length;
41713         }
41714 };
41715 _extends(CharacterData,Node);
41716 function Text() {
41717 }
41718 Text.prototype = {
41719         nodeName : "#text",
41720         nodeType : TEXT_NODE,
41721         splitText : function(offset) {
41722                 var text = this.data;
41723                 var newText = text.substring(offset);
41724                 text = text.substring(0, offset);
41725                 this.data = this.nodeValue = text;
41726                 this.length = text.length;
41727                 var newNode = this.ownerDocument.createTextNode(newText);
41728                 if(this.parentNode){
41729                         this.parentNode.insertBefore(newNode, this.nextSibling);
41730                 }
41731                 return newNode;
41732         }
41733 };
41734 _extends(Text,CharacterData);
41735 function Comment() {
41736 }
41737 Comment.prototype = {
41738         nodeName : "#comment",
41739         nodeType : COMMENT_NODE
41740 };
41741 _extends(Comment,CharacterData);
41742
41743 function CDATASection() {
41744 }
41745 CDATASection.prototype = {
41746         nodeName : "#cdata-section",
41747         nodeType : CDATA_SECTION_NODE
41748 };
41749 _extends(CDATASection,CharacterData);
41750
41751
41752 function DocumentType() {
41753 }
41754 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41755 _extends(DocumentType,Node);
41756
41757 function Notation() {
41758 }
41759 Notation.prototype.nodeType = NOTATION_NODE;
41760 _extends(Notation,Node);
41761
41762 function Entity() {
41763 }
41764 Entity.prototype.nodeType = ENTITY_NODE;
41765 _extends(Entity,Node);
41766
41767 function EntityReference() {
41768 }
41769 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41770 _extends(EntityReference,Node);
41771
41772 function DocumentFragment() {
41773 }
41774 DocumentFragment.prototype.nodeName =   "#document-fragment";
41775 DocumentFragment.prototype.nodeType =   DOCUMENT_FRAGMENT_NODE;
41776 _extends(DocumentFragment,Node);
41777
41778
41779 function ProcessingInstruction() {
41780 }
41781 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41782 _extends(ProcessingInstruction,Node);
41783 function XMLSerializer(){}
41784 XMLSerializer.prototype.serializeToString = function(node,attributeSorter){
41785         return node.toString(attributeSorter);
41786 };
41787 Node.prototype.toString =function(attributeSorter){
41788         var buf = [];
41789         serializeToString(this,buf,attributeSorter);
41790         return buf.join('');
41791 };
41792 function serializeToString(node,buf,attributeSorter,isHTML){
41793         switch(node.nodeType){
41794         case ELEMENT_NODE:
41795                 var attrs = node.attributes;
41796                 var len = attrs.length;
41797                 var child = node.firstChild;
41798                 var nodeName = node.tagName;
41799                 isHTML =  (htmlns === node.namespaceURI) ||isHTML; 
41800                 buf.push('<',nodeName);
41801                 if(attributeSorter){
41802                         buf.sort.apply(attrs, attributeSorter);
41803                 }
41804                 for(var i=0;i<len;i++){
41805                         serializeToString(attrs.item(i),buf,attributeSorter,isHTML);
41806                 }
41807                 if(child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)){
41808                         buf.push('>');
41809                         //if is cdata child node
41810                         if(isHTML && /^script$/i.test(nodeName)){
41811                                 if(child){
41812                                         buf.push(child.data);
41813                                 }
41814                         }else{
41815                                 while(child){
41816                                         serializeToString(child,buf,attributeSorter,isHTML);
41817                                         child = child.nextSibling;
41818                                 }
41819                         }
41820                         buf.push('</',nodeName,'>');
41821                 }else{
41822                         buf.push('/>');
41823                 }
41824                 return;
41825         case DOCUMENT_NODE:
41826         case DOCUMENT_FRAGMENT_NODE:
41827                 var child = node.firstChild;
41828                 while(child){
41829                         serializeToString(child,buf,attributeSorter,isHTML);
41830                         child = child.nextSibling;
41831                 }
41832                 return;
41833         case ATTRIBUTE_NODE:
41834                 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
41835         case TEXT_NODE:
41836                 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
41837         case CDATA_SECTION_NODE:
41838                 return buf.push( '<![CDATA[',node.data,']]>');
41839         case COMMENT_NODE:
41840                 return buf.push( "<!--",node.data,"-->");
41841         case DOCUMENT_TYPE_NODE:
41842                 var pubid = node.publicId;
41843                 var sysid = node.systemId;
41844                 buf.push('<!DOCTYPE ',node.name);
41845                 if(pubid){
41846                         buf.push(' PUBLIC "',pubid);
41847                         if (sysid && sysid!='.') {
41848                                 buf.push( '" "',sysid);
41849                         }
41850                         buf.push('">');
41851                 }else if(sysid && sysid!='.'){
41852                         buf.push(' SYSTEM "',sysid,'">');
41853                 }else{
41854                         var sub = node.internalSubset;
41855                         if(sub){
41856                                 buf.push(" [",sub,"]");
41857                         }
41858                         buf.push(">");
41859                 }
41860                 return;
41861         case PROCESSING_INSTRUCTION_NODE:
41862                 return buf.push( "<?",node.target," ",node.data,"?>");
41863         case ENTITY_REFERENCE_NODE:
41864                 return buf.push( '&',node.nodeName,';');
41865         //case ENTITY_NODE:
41866         //case NOTATION_NODE:
41867         default:
41868                 buf.push('??',node.nodeName);
41869         }
41870 }
41871 function importNode(doc,node,deep){
41872         var node2;
41873         switch (node.nodeType) {
41874         case ELEMENT_NODE:
41875                 node2 = node.cloneNode(false);
41876                 node2.ownerDocument = doc;
41877                 //var attrs = node2.attributes;
41878                 //var len = attrs.length;
41879                 //for(var i=0;i<len;i++){
41880                         //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
41881                 //}
41882         case DOCUMENT_FRAGMENT_NODE:
41883                 break;
41884         case ATTRIBUTE_NODE:
41885                 deep = true;
41886                 break;
41887         //case ENTITY_REFERENCE_NODE:
41888         //case PROCESSING_INSTRUCTION_NODE:
41889         ////case TEXT_NODE:
41890         //case CDATA_SECTION_NODE:
41891         //case COMMENT_NODE:
41892         //      deep = false;
41893         //      break;
41894         //case DOCUMENT_NODE:
41895         //case DOCUMENT_TYPE_NODE:
41896         //cannot be imported.
41897         //case ENTITY_NODE:
41898         //case NOTATION_NODE:
41899         //can not hit in level3
41900         //default:throw e;
41901         }
41902         if(!node2){
41903                 node2 = node.cloneNode(false);//false
41904         }
41905         node2.ownerDocument = doc;
41906         node2.parentNode = null;
41907         if(deep){
41908                 var child = node.firstChild;
41909                 while(child){
41910                         node2.appendChild(importNode(doc,child,deep));
41911                         child = child.nextSibling;
41912                 }
41913         }
41914         return node2;
41915 }
41916 //
41917 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
41918 //                                      attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
41919 function cloneNode(doc,node,deep){
41920         var node2 = new node.constructor();
41921         for(var n in node){
41922                 var v = node[n];
41923                 if(typeof v != 'object' ){
41924                         if(v != node2[n]){
41925                                 node2[n] = v;
41926                         }
41927                 }
41928         }
41929         if(node.childNodes){
41930                 node2.childNodes = new NodeList();
41931         }
41932         node2.ownerDocument = doc;
41933         switch (node2.nodeType) {
41934         case ELEMENT_NODE:
41935                 var attrs       = node.attributes;
41936                 var attrs2      = node2.attributes = new NamedNodeMap();
41937                 var len = attrs.length;
41938                 attrs2._ownerElement = node2;
41939                 for(var i=0;i<len;i++){
41940                         node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
41941                 }
41942                 break;;
41943         case ATTRIBUTE_NODE:
41944                 deep = true;
41945         }
41946         if(deep){
41947                 var child = node.firstChild;
41948                 while(child){
41949                         node2.appendChild(cloneNode(doc,child,deep));
41950                         child = child.nextSibling;
41951                 }
41952         }
41953         return node2;
41954 }
41955
41956 function __set__(object,key,value){
41957         object[key] = value;
41958 }
41959 //do dynamic
41960 try{
41961         if(Object.defineProperty){
41962                 Object.defineProperty(LiveNodeList.prototype,'length',{
41963                         get:function(){
41964                                 _updateLiveList(this);
41965                                 return this.$$length;
41966                         }
41967                 });
41968                 Object.defineProperty(Node.prototype,'textContent',{
41969                         get:function(){
41970                                 return getTextContent(this);
41971                         },
41972                         set:function(data){
41973                                 switch(this.nodeType){
41974                                 case 1:
41975                                 case 11:
41976                                         while(this.firstChild){
41977                                                 this.removeChild(this.firstChild);
41978                                         }
41979                                         if(data || String(data)){
41980                                                 this.appendChild(this.ownerDocument.createTextNode(data));
41981                                         }
41982                                         break;
41983                                 default:
41984                                         //TODO:
41985                                         this.data = data;
41986                                         this.value = value;
41987                                         this.nodeValue = data;
41988                                 }
41989                         }
41990                 });
41991                 
41992                 function getTextContent(node){
41993                         switch(node.nodeType){
41994                         case 1:
41995                         case 11:
41996                                 var buf = [];
41997                                 node = node.firstChild;
41998                                 while(node){
41999                                         if(node.nodeType!==7 && node.nodeType !==8){
42000                                                 buf.push(getTextContent(node));
42001                                         }
42002                                         node = node.nextSibling;
42003                                 }
42004                                 return buf.join('');
42005                         default:
42006                                 return node.nodeValue;
42007                         }
42008                 }
42009                 __set__ = function(object,key,value){
42010                         //console.log(value)
42011                         object['$$'+key] = value;
42012                 };
42013         }
42014 }catch(e){//ie8
42015 }
42016
42017 if(typeof commonjsRequire == 'function'){
42018         exports.DOMImplementation = DOMImplementation;
42019         exports.XMLSerializer = XMLSerializer;
42020 }
42021 });
42022
42023 var domParser = createCommonjsModule(function (module, exports) {
42024 function DOMParser(options){
42025         this.options = options ||{locator:{}};
42026         
42027 }
42028 DOMParser.prototype.parseFromString = function(source,mimeType){        
42029         var options = this.options;
42030         var sax$$1 =  new XMLReader();
42031         var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
42032         var errorHandler = options.errorHandler;
42033         var locator = options.locator;
42034         var defaultNSMap = options.xmlns||{};
42035         var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
42036         if(locator){
42037                 domBuilder.setDocumentLocator(locator);
42038         }
42039         
42040         sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
42041         sax$$1.domBuilder = options.domBuilder || domBuilder;
42042         if(/\/x?html?$/.test(mimeType)){
42043                 entityMap.nbsp = '\xa0';
42044                 entityMap.copy = '\xa9';
42045                 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
42046         }
42047         defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
42048         if(source){
42049                 sax$$1.parse(source,defaultNSMap,entityMap);
42050         }else{
42051                 sax$$1.errorHandler.error("invalid document source");
42052         }
42053         return domBuilder.document;
42054 };
42055 function buildErrorHandler(errorImpl,domBuilder,locator){
42056         if(!errorImpl){
42057                 if(domBuilder instanceof DOMHandler){
42058                         return domBuilder;
42059                 }
42060                 errorImpl = domBuilder ;
42061         }
42062         var errorHandler = {};
42063         var isCallback = errorImpl instanceof Function;
42064         locator = locator||{};
42065         function build(key){
42066                 var fn = errorImpl[key];
42067                 if(!fn && isCallback){
42068                         fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
42069                 }
42070                 errorHandler[key] = fn && function(msg){
42071                         fn('[xmldom '+key+']\t'+msg+_locator(locator));
42072                 }||function(){};
42073         }
42074         build('warning');
42075         build('error');
42076         build('fatalError');
42077         return errorHandler;
42078 }
42079
42080 //console.log('#\n\n\n\n\n\n\n####')
42081 /**
42082  * +ContentHandler+ErrorHandler
42083  * +LexicalHandler+EntityResolver2
42084  * -DeclHandler-DTDHandler 
42085  * 
42086  * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
42087  * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
42088  * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
42089  */
42090 function DOMHandler() {
42091     this.cdata = false;
42092 }
42093 function position(locator,node){
42094         node.lineNumber = locator.lineNumber;
42095         node.columnNumber = locator.columnNumber;
42096 }
42097 /**
42098  * @see org.xml.sax.ContentHandler#startDocument
42099  * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
42100  */ 
42101 DOMHandler.prototype = {
42102         startDocument : function() {
42103         this.document = new DOMImplementation().createDocument(null, null, null);
42104         if (this.locator) {
42105                 this.document.documentURI = this.locator.systemId;
42106         }
42107         },
42108         startElement:function(namespaceURI, localName, qName, attrs) {
42109                 var doc = this.document;
42110             var el = doc.createElementNS(namespaceURI, qName||localName);
42111             var len = attrs.length;
42112             appendElement(this, el);
42113             this.currentElement = el;
42114             
42115                 this.locator && position(this.locator,el);
42116             for (var i = 0 ; i < len; i++) {
42117                 var namespaceURI = attrs.getURI(i);
42118                 var value = attrs.getValue(i);
42119                 var qName = attrs.getQName(i);
42120                         var attr = doc.createAttributeNS(namespaceURI, qName);
42121                         if( attr.getOffset){
42122                                 position(attr.getOffset(1),attr);
42123                         }
42124                         attr.value = attr.nodeValue = value;
42125                         el.setAttributeNode(attr);
42126             }
42127         },
42128         endElement:function(namespaceURI, localName, qName) {
42129                 var current = this.currentElement;
42130             var tagName = current.tagName;
42131             this.currentElement = current.parentNode;
42132         },
42133         startPrefixMapping:function(prefix, uri) {
42134         },
42135         endPrefixMapping:function(prefix) {
42136         },
42137         processingInstruction:function(target, data) {
42138             var ins = this.document.createProcessingInstruction(target, data);
42139             this.locator && position(this.locator,ins);
42140             appendElement(this, ins);
42141         },
42142         ignorableWhitespace:function(ch, start, length) {
42143         },
42144         characters:function(chars, start, length) {
42145                 chars = _toString.apply(this,arguments);
42146                 //console.log(chars)
42147                 if(this.currentElement && chars){
42148                         if (this.cdata) {
42149                                 var charNode = this.document.createCDATASection(chars);
42150                                 this.currentElement.appendChild(charNode);
42151                         } else {
42152                                 var charNode = this.document.createTextNode(chars);
42153                                 this.currentElement.appendChild(charNode);
42154                         }
42155                         this.locator && position(this.locator,charNode);
42156                 }
42157         },
42158         skippedEntity:function(name) {
42159         },
42160         endDocument:function() {
42161                 this.document.normalize();
42162         },
42163         setDocumentLocator:function (locator) {
42164             if(this.locator = locator){// && !('lineNumber' in locator)){
42165                 locator.lineNumber = 0;
42166             }
42167         },
42168         //LexicalHandler
42169         comment:function(chars, start, length) {
42170                 chars = _toString.apply(this,arguments);
42171             var comm = this.document.createComment(chars);
42172             this.locator && position(this.locator,comm);
42173             appendElement(this, comm);
42174         },
42175         
42176         startCDATA:function() {
42177             //used in characters() methods
42178             this.cdata = true;
42179         },
42180         endCDATA:function() {
42181             this.cdata = false;
42182         },
42183         
42184         startDTD:function(name, publicId, systemId) {
42185                 var impl = this.document.implementation;
42186             if (impl && impl.createDocumentType) {
42187                 var dt = impl.createDocumentType(name, publicId, systemId);
42188                 this.locator && position(this.locator,dt);
42189                 appendElement(this, dt);
42190             }
42191         },
42192         /**
42193          * @see org.xml.sax.ErrorHandler
42194          * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
42195          */
42196         warning:function(error) {
42197                 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
42198         },
42199         error:function(error) {
42200                 console.error('[xmldom error]\t'+error,_locator(this.locator));
42201         },
42202         fatalError:function(error) {
42203                 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
42204             throw error;
42205         }
42206 };
42207 function _locator(l){
42208         if(l){
42209                 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
42210         }
42211 }
42212 function _toString(chars,start,length){
42213         if(typeof chars == 'string'){
42214                 return chars.substr(start,length)
42215         }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
42216                 if(chars.length >= start+length || start){
42217                         return new java.lang.String(chars,start,length)+'';
42218                 }
42219                 return chars;
42220         }
42221 }
42222
42223 /*
42224  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
42225  * used method of org.xml.sax.ext.LexicalHandler:
42226  *  #comment(chars, start, length)
42227  *  #startCDATA()
42228  *  #endCDATA()
42229  *  #startDTD(name, publicId, systemId)
42230  *
42231  *
42232  * IGNORED method of org.xml.sax.ext.LexicalHandler:
42233  *  #endDTD()
42234  *  #startEntity(name)
42235  *  #endEntity(name)
42236  *
42237  *
42238  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
42239  * IGNORED method of org.xml.sax.ext.DeclHandler
42240  *      #attributeDecl(eName, aName, type, mode, value)
42241  *  #elementDecl(name, model)
42242  *  #externalEntityDecl(name, publicId, systemId)
42243  *  #internalEntityDecl(name, value)
42244  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
42245  * IGNORED method of org.xml.sax.EntityResolver2
42246  *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
42247  *  #resolveEntity(publicId, systemId)
42248  *  #getExternalSubset(name, baseURI)
42249  * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
42250  * IGNORED method of org.xml.sax.DTDHandler
42251  *  #notationDecl(name, publicId, systemId) {};
42252  *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
42253  */
42254 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
42255         DOMHandler.prototype[key] = function(){return null};
42256 });
42257
42258 /* 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 */
42259 function appendElement (hander,node) {
42260     if (!hander.currentElement) {
42261         hander.document.appendChild(node);
42262     } else {
42263         hander.currentElement.appendChild(node);
42264     }
42265 }//appendChild and setAttributeNS are preformance key
42266
42267 if(typeof commonjsRequire == 'function'){
42268         var XMLReader = sax.XMLReader;
42269         var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
42270         exports.XMLSerializer = dom.XMLSerializer ;
42271         exports.DOMParser = DOMParser;
42272 }
42273 });
42274
42275 var togeojson = createCommonjsModule(function (module, exports) {
42276 var toGeoJSON = (function() {
42277     'use strict';
42278
42279     var removeSpace = /\s*/g,
42280         trimSpace = /^\s*|\s*$/g,
42281         splitSpace = /\s+/;
42282     // generate a short, numeric hash of a string
42283     function okhash(x) {
42284         if (!x || !x.length) return 0;
42285         for (var i = 0, h = 0; i < x.length; i++) {
42286             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
42287         } return h;
42288     }
42289     // all Y children of X
42290     function get(x, y) { return x.getElementsByTagName(y); }
42291     function attr(x, y) { return x.getAttribute(y); }
42292     function attrf(x, y) { return parseFloat(attr(x, y)); }
42293     // one Y child of X, if any, otherwise null
42294     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
42295     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
42296     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
42297     // cast array x into numbers
42298     function numarray(x) {
42299         for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
42300         return o;
42301     }
42302     // get the content of a text node, if any
42303     function nodeVal(x) {
42304         if (x) { norm(x); }
42305         return (x && x.textContent) || '';
42306     }
42307     // get the contents of multiple text nodes, if present
42308     function getMulti(x, ys) {
42309         var o = {}, n, k;
42310         for (k = 0; k < ys.length; k++) {
42311             n = get1(x, ys[k]);
42312             if (n) o[ys[k]] = nodeVal(n);
42313         }
42314         return o;
42315     }
42316     // add properties of Y to X, overwriting if present in both
42317     function extend(x, y) { for (var k in y) x[k] = y[k]; }
42318     // get one coordinate from a coordinate array, if any
42319     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
42320     // get all coordinates from a coordinate array as [[],[]]
42321     function coord(v) {
42322         var coords = v.replace(trimSpace, '').split(splitSpace),
42323             o = [];
42324         for (var i = 0; i < coords.length; i++) {
42325             o.push(coord1(coords[i]));
42326         }
42327         return o;
42328     }
42329     function coordPair(x) {
42330         var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
42331             ele = get1(x, 'ele'),
42332             // handle namespaced attribute in browser
42333             heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
42334             time = get1(x, 'time'),
42335             e;
42336         if (ele) {
42337             e = parseFloat(nodeVal(ele));
42338             if (!isNaN(e)) {
42339                 ll.push(e);
42340             }
42341         }
42342         return {
42343             coordinates: ll,
42344             time: time ? nodeVal(time) : null,
42345             heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
42346         };
42347     }
42348
42349     // create a new feature collection parent object
42350     function fc() {
42351         return {
42352             type: 'FeatureCollection',
42353             features: []
42354         };
42355     }
42356
42357     var serializer;
42358     if (typeof XMLSerializer !== 'undefined') {
42359         /* istanbul ignore next */
42360         serializer = new XMLSerializer();
42361     // only require xmldom in a node environment
42362     } else if ('object' === 'object' && typeof process === 'object' && !process.browser) {
42363         serializer = new (domParser.XMLSerializer)();
42364     }
42365     function xml2str(str) {
42366         // IE9 will create a new XMLSerializer but it'll crash immediately.
42367         // This line is ignored because we don't run coverage tests in IE9
42368         /* istanbul ignore next */
42369         if (str.xml !== undefined) return str.xml;
42370         return serializer.serializeToString(str);
42371     }
42372
42373     var t = {
42374         kml: function(doc) {
42375
42376             var gj = fc(),
42377                 // styleindex keeps track of hashed styles in order to match features
42378                 styleIndex = {}, styleByHash = {},
42379                 // stylemapindex keeps track of style maps to expose in properties
42380                 styleMapIndex = {},
42381                 // atomic geospatial types supported by KML - MultiGeometry is
42382                 // handled separately
42383                 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
42384                 // all root placemarks in the file
42385                 placemarks = get(doc, 'Placemark'),
42386                 styles = get(doc, 'Style'),
42387                 styleMaps = get(doc, 'StyleMap');
42388
42389             for (var k = 0; k < styles.length; k++) {
42390                 var hash = okhash(xml2str(styles[k])).toString(16);
42391                 styleIndex['#' + attr(styles[k], 'id')] = hash;
42392                 styleByHash[hash] = styles[k];
42393             }
42394             for (var l = 0; l < styleMaps.length; l++) {
42395                 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
42396                 var pairs = get(styleMaps[l], 'Pair');
42397                 var pairsMap = {};
42398                 for (var m = 0; m < pairs.length; m++) {
42399                     pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
42400                 }
42401                 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
42402
42403             }
42404             for (var j = 0; j < placemarks.length; j++) {
42405                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
42406             }
42407             function kmlColor(v) {
42408                 var color, opacity;
42409                 v = v || '';
42410                 if (v.substr(0, 1) === '#') { v = v.substr(1); }
42411                 if (v.length === 6 || v.length === 3) { color = v; }
42412                 if (v.length === 8) {
42413                     opacity = parseInt(v.substr(0, 2), 16) / 255;
42414                     color = '#' + v.substr(6, 2) +
42415                         v.substr(4, 2) +
42416                         v.substr(2, 2);
42417                 }
42418                 return [color, isNaN(opacity) ? undefined : opacity];
42419             }
42420             function gxCoord(v) { return numarray(v.split(' ')); }
42421             function gxCoords(root) {
42422                 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
42423                 if (elems.length === 0) elems = get(root, 'gx:coord');
42424                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
42425                 var timeElems = get(root, 'when');
42426                 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
42427                 return {
42428                     coords: coords,
42429                     times: times
42430                 };
42431             }
42432             function getGeometry(root) {
42433                 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
42434                 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
42435                 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
42436                 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
42437                 for (i = 0; i < geotypes.length; i++) {
42438                     geomNodes = get(root, geotypes[i]);
42439                     if (geomNodes) {
42440                         for (j = 0; j < geomNodes.length; j++) {
42441                             geomNode = geomNodes[j];
42442                             if (geotypes[i] === 'Point') {
42443                                 geoms.push({
42444                                     type: 'Point',
42445                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
42446                                 });
42447                             } else if (geotypes[i] === 'LineString') {
42448                                 geoms.push({
42449                                     type: 'LineString',
42450                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
42451                                 });
42452                             } else if (geotypes[i] === 'Polygon') {
42453                                 var rings = get(geomNode, 'LinearRing'),
42454                                     coords = [];
42455                                 for (k = 0; k < rings.length; k++) {
42456                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
42457                                 }
42458                                 geoms.push({
42459                                     type: 'Polygon',
42460                                     coordinates: coords
42461                                 });
42462                             } else if (geotypes[i] === 'Track' ||
42463                                 geotypes[i] === 'gx:Track') {
42464                                 var track = gxCoords(geomNode);
42465                                 geoms.push({
42466                                     type: 'LineString',
42467                                     coordinates: track.coords
42468                                 });
42469                                 if (track.times.length) coordTimes.push(track.times);
42470                             }
42471                         }
42472                     }
42473                 }
42474                 return {
42475                     geoms: geoms,
42476                     coordTimes: coordTimes
42477                 };
42478             }
42479             function getPlacemark(root) {
42480                 var geomsAndTimes = getGeometry(root), i, properties = {},
42481                     name = nodeVal(get1(root, 'name')),
42482                     address = nodeVal(get1(root, 'address')),
42483                     styleUrl = nodeVal(get1(root, 'styleUrl')),
42484                     description = nodeVal(get1(root, 'description')),
42485                     timeSpan = get1(root, 'TimeSpan'),
42486                     timeStamp = get1(root, 'TimeStamp'),
42487                     extendedData = get1(root, 'ExtendedData'),
42488                     lineStyle = get1(root, 'LineStyle'),
42489                     polyStyle = get1(root, 'PolyStyle'),
42490                     visibility = get1(root, 'visibility');
42491
42492                 if (!geomsAndTimes.geoms.length) return [];
42493                 if (name) properties.name = name;
42494                 if (address) properties.address = address;
42495                 if (styleUrl) {
42496                     if (styleUrl[0] !== '#') {
42497                         styleUrl = '#' + styleUrl;
42498                     }
42499
42500                     properties.styleUrl = styleUrl;
42501                     if (styleIndex[styleUrl]) {
42502                         properties.styleHash = styleIndex[styleUrl];
42503                     }
42504                     if (styleMapIndex[styleUrl]) {
42505                         properties.styleMapHash = styleMapIndex[styleUrl];
42506                         properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42507                     }
42508                     // Try to populate the lineStyle or polyStyle since we got the style hash
42509                     var style = styleByHash[properties.styleHash];
42510                     if (style) {
42511                         if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42512                         if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42513                     }
42514                 }
42515                 if (description) properties.description = description;
42516                 if (timeSpan) {
42517                     var begin = nodeVal(get1(timeSpan, 'begin'));
42518                     var end = nodeVal(get1(timeSpan, 'end'));
42519                     properties.timespan = { begin: begin, end: end };
42520                 }
42521                 if (timeStamp) {
42522                     properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42523                 }
42524                 if (lineStyle) {
42525                     var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42526                         color = linestyles[0],
42527                         opacity = linestyles[1],
42528                         width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42529                     if (color) properties.stroke = color;
42530                     if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42531                     if (!isNaN(width)) properties['stroke-width'] = width;
42532                 }
42533                 if (polyStyle) {
42534                     var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42535                         pcolor = polystyles[0],
42536                         popacity = polystyles[1],
42537                         fill = nodeVal(get1(polyStyle, 'fill')),
42538                         outline = nodeVal(get1(polyStyle, 'outline'));
42539                     if (pcolor) properties.fill = pcolor;
42540                     if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42541                     if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42542                     if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42543                 }
42544                 if (extendedData) {
42545                     var datas = get(extendedData, 'Data'),
42546                         simpleDatas = get(extendedData, 'SimpleData');
42547
42548                     for (i = 0; i < datas.length; i++) {
42549                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42550                     }
42551                     for (i = 0; i < simpleDatas.length; i++) {
42552                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42553                     }
42554                 }
42555                 if (visibility) {
42556                     properties.visibility = nodeVal(visibility);
42557                 }
42558                 if (geomsAndTimes.coordTimes.length) {
42559                     properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42560                         geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42561                 }
42562                 var feature = {
42563                     type: 'Feature',
42564                     geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42565                         type: 'GeometryCollection',
42566                         geometries: geomsAndTimes.geoms
42567                     },
42568                     properties: properties
42569                 };
42570                 if (attr(root, 'id')) feature.id = attr(root, 'id');
42571                 return [feature];
42572             }
42573             return gj;
42574         },
42575         gpx: function(doc) {
42576             var i,
42577                 tracks = get(doc, 'trk'),
42578                 routes = get(doc, 'rte'),
42579                 waypoints = get(doc, 'wpt'),
42580                 // a feature collection
42581                 gj = fc(),
42582                 feature;
42583             for (i = 0; i < tracks.length; i++) {
42584                 feature = getTrack(tracks[i]);
42585                 if (feature) gj.features.push(feature);
42586             }
42587             for (i = 0; i < routes.length; i++) {
42588                 feature = getRoute(routes[i]);
42589                 if (feature) gj.features.push(feature);
42590             }
42591             for (i = 0; i < waypoints.length; i++) {
42592                 gj.features.push(getPoint(waypoints[i]));
42593             }
42594             function getPoints(node, pointname) {
42595                 var pts = get(node, pointname),
42596                     line = [],
42597                     times = [],
42598                     heartRates = [],
42599                     l = pts.length;
42600                 if (l < 2) return {};  // Invalid line in GeoJSON
42601                 for (var i = 0; i < l; i++) {
42602                     var c = coordPair(pts[i]);
42603                     line.push(c.coordinates);
42604                     if (c.time) times.push(c.time);
42605                     if (c.heartRate) heartRates.push(c.heartRate);
42606                 }
42607                 return {
42608                     line: line,
42609                     times: times,
42610                     heartRates: heartRates
42611                 };
42612             }
42613             function getTrack(node) {
42614                 var segments = get(node, 'trkseg'),
42615                     track = [],
42616                     times = [],
42617                     heartRates = [],
42618                     line;
42619                 for (var i = 0; i < segments.length; i++) {
42620                     line = getPoints(segments[i], 'trkpt');
42621                     if (line) {
42622                         if (line.line) track.push(line.line);
42623                         if (line.times && line.times.length) times.push(line.times);
42624                         if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42625                     }
42626                 }
42627                 if (track.length === 0) return;
42628                 var properties = getProperties(node);
42629                 extend(properties, getLineStyle(get1(node, 'extensions')));
42630                 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42631                 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42632                 return {
42633                     type: 'Feature',
42634                     properties: properties,
42635                     geometry: {
42636                         type: track.length === 1 ? 'LineString' : 'MultiLineString',
42637                         coordinates: track.length === 1 ? track[0] : track
42638                     }
42639                 };
42640             }
42641             function getRoute(node) {
42642                 var line = getPoints(node, 'rtept');
42643                 if (!line.line) return;
42644                 var prop = getProperties(node);
42645                 extend(prop, getLineStyle(get1(node, 'extensions')));
42646                 var routeObj = {
42647                     type: 'Feature',
42648                     properties: prop,
42649                     geometry: {
42650                         type: 'LineString',
42651                         coordinates: line.line
42652                     }
42653                 };
42654                 return routeObj;
42655             }
42656             function getPoint(node) {
42657                 var prop = getProperties(node);
42658                 extend(prop, getMulti(node, ['sym']));
42659                 return {
42660                     type: 'Feature',
42661                     properties: prop,
42662                     geometry: {
42663                         type: 'Point',
42664                         coordinates: coordPair(node).coordinates
42665                     }
42666                 };
42667             }
42668             function getLineStyle(extensions) {
42669                 var style = {};
42670                 if (extensions) {
42671                     var lineStyle = get1(extensions, 'line');
42672                     if (lineStyle) {
42673                         var color = nodeVal(get1(lineStyle, 'color')),
42674                             opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))),
42675                             width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42676                         if (color) style.stroke = color;
42677                         if (!isNaN(opacity)) style['stroke-opacity'] = opacity;
42678                         // GPX width is in mm, convert to px with 96 px per inch
42679                         if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4;
42680                     }
42681                 }
42682                 return style;
42683             }
42684             function getProperties(node) {
42685                 var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']),
42686                     links = get(node, 'link');
42687                 if (links.length) prop.links = [];
42688                 for (var i = 0, link; i < links.length; i++) {
42689                     link = { href: attr(links[i], 'href') };
42690                     extend(link, getMulti(links[i], ['text', 'type']));
42691                     prop.links.push(link);
42692                 }
42693                 return prop;
42694             }
42695             return gj;
42696         }
42697     };
42698     return t;
42699 })();
42700
42701 module.exports = toGeoJSON;
42702 });
42703
42704 function svgGpx(projection, context, dispatch$$1) {
42705     var showLabels = true,
42706         detected = utilDetect(),
42707         layer;
42708
42709
42710     function init() {
42711         if (svgGpx.initialized) return;  // run once
42712
42713         svgGpx.geojson = {};
42714         svgGpx.enabled = true;
42715
42716         function over() {
42717             event.stopPropagation();
42718             event.preventDefault();
42719             event.dataTransfer.dropEffect = 'copy';
42720         }
42721
42722         select('body')
42723             .attr('dropzone', 'copy')
42724             .on('drop.localgpx', function() {
42725                 event.stopPropagation();
42726                 event.preventDefault();
42727                 if (!detected.filedrop) return;
42728                 drawGpx.files(event.dataTransfer.files);
42729             })
42730             .on('dragenter.localgpx', over)
42731             .on('dragexit.localgpx', over)
42732             .on('dragover.localgpx', over);
42733
42734         svgGpx.initialized = true;
42735     }
42736
42737
42738     function drawGpx(selection$$1) {
42739         var geojson = svgGpx.geojson,
42740             enabled = svgGpx.enabled;
42741
42742         layer = selection$$1.selectAll('.layer-gpx')
42743             .data(enabled ? [0] : []);
42744
42745         layer.exit()
42746             .remove();
42747
42748         layer = layer.enter()
42749             .append('g')
42750             .attr('class', 'layer-gpx')
42751             .merge(layer);
42752
42753
42754         var paths = layer
42755             .selectAll('path')
42756             .data([geojson]);
42757
42758         paths.exit()
42759             .remove();
42760
42761         paths = paths.enter()
42762             .append('path')
42763             .attr('class', 'gpx')
42764             .merge(paths);
42765
42766
42767         var path$$1 = index$4(projection);
42768
42769         paths
42770             .attr('d', path$$1);
42771
42772
42773         var labels = layer.selectAll('text')
42774             .data(showLabels && geojson.features ? geojson.features : []);
42775
42776         labels.exit()
42777             .remove();
42778
42779         labels = labels.enter()
42780             .append('text')
42781             .attr('class', 'gpx')
42782             .merge(labels);
42783
42784         labels
42785             .text(function(d) {
42786                 return d.properties.desc || d.properties.name;
42787             })
42788             .attr('x', function(d) {
42789                 var centroid = path$$1.centroid(d);
42790                 return centroid[0] + 7;
42791             })
42792             .attr('y', function(d) {
42793                 var centroid = path$$1.centroid(d);
42794                 return centroid[1];
42795             });
42796
42797     }
42798
42799
42800     function toDom(x) {
42801         return (new DOMParser()).parseFromString(x, 'text/xml');
42802     }
42803
42804
42805     function getExtension(fileName) {
42806         if (lodash.isUndefined(fileName)) {
42807             return '';
42808         }
42809
42810         var lastDotIndex = fileName.lastIndexOf('.');
42811         if (lastDotIndex < 0) {
42812             return '';
42813         }
42814
42815         return fileName.substr(lastDotIndex);
42816     }
42817
42818
42819     function parseSaveAndZoom(extension, data) {
42820         switch (extension) {
42821             default:
42822                 drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
42823                 break;
42824             case '.kml':
42825                 drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
42826                 break;
42827             case '.geojson':
42828             case '.json':
42829                 drawGpx.geojson(JSON.parse(data)).fitZoom();
42830                 break;
42831         }
42832     }
42833
42834
42835     drawGpx.showLabels = function(_) {
42836         if (!arguments.length) return showLabels;
42837         showLabels = _;
42838         return this;
42839     };
42840
42841
42842     drawGpx.enabled = function(_) {
42843         if (!arguments.length) return svgGpx.enabled;
42844         svgGpx.enabled = _;
42845         dispatch$$1.call('change');
42846         return this;
42847     };
42848
42849
42850     drawGpx.hasGpx = function() {
42851         var geojson = svgGpx.geojson;
42852         return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42853     };
42854
42855
42856     drawGpx.geojson = function(gj) {
42857         if (!arguments.length) return svgGpx.geojson;
42858         if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42859         svgGpx.geojson = gj;
42860         dispatch$$1.call('change');
42861         return this;
42862     };
42863
42864
42865     drawGpx.url = function(url) {
42866         text(url, function(err, data) {
42867             if (!err) {
42868                 var extension = getExtension(url);
42869                 parseSaveAndZoom(extension, data);
42870             }
42871         });
42872         return this;
42873     };
42874
42875
42876     drawGpx.files = function(fileList) {
42877         if (!fileList.length) return this;
42878         var f = fileList[0],
42879             reader = new FileReader();
42880
42881         reader.onload = (function(file) {
42882             var extension = getExtension(file.name);
42883
42884             return function (e) {
42885                 parseSaveAndZoom(extension, e.target.result);
42886             };
42887         })(f);
42888
42889         reader.readAsText(f);
42890         return this;
42891     };
42892
42893
42894     drawGpx.fitZoom = function() {
42895         if (!this.hasGpx()) return this;
42896         var geojson = svgGpx.geojson;
42897
42898         var map$$1 = context.map(),
42899             viewport = map$$1.trimmedExtent().polygon(),
42900             coords = lodash.reduce(geojson.features, function(coords, feature) {
42901                 var c = feature.geometry.coordinates;
42902
42903                 /* eslint-disable no-fallthrough */
42904                 switch (feature.geometry.type) {
42905                     case 'Point':
42906                         c = [c];
42907                     case 'MultiPoint':
42908                     case 'LineString':
42909                         break;
42910
42911                     case 'MultiPolygon':
42912                         c = lodash.flatten(c);
42913                     case 'Polygon':
42914                     case 'MultiLineString':
42915                         c = lodash.flatten(c);
42916                         break;
42917                 }
42918                 /* eslint-enable no-fallthrough */
42919
42920                 return lodash.union(coords, c);
42921             }, []);
42922
42923         if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42924             var extent$$1 = geoExtent$$1(bounds({ type: 'LineString', coordinates: coords }));
42925             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
42926         }
42927
42928         return this;
42929     };
42930
42931
42932     init();
42933     return drawGpx;
42934 }
42935
42936 function svgIcon(name, svgklass, useklass) {
42937     return function drawIcon(selection) {
42938         selection.selectAll('svg')
42939             .data([0])
42940             .enter()
42941             .append('svg')
42942             .attr('class', 'icon ' + (svgklass || ''))
42943             .append('use')
42944             .attr('xlink:href', name)
42945             .attr('class', useklass);
42946     };
42947 }
42948
42949 function svgLabels(projection, context) {
42950     var path$$1 = index$4(projection),
42951         detected = utilDetect(),
42952         baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
42953         rdrawn = index$9(),
42954         rskipped = index$9(),
42955         textWidthCache = {},
42956         entitybboxes = {};
42957
42958     // Listed from highest to lowest priority
42959     var labelStack = [
42960         ['line', 'aeroway', '*', 12],
42961         ['line', 'highway', 'motorway', 12],
42962         ['line', 'highway', 'trunk', 12],
42963         ['line', 'highway', 'primary', 12],
42964         ['line', 'highway', 'secondary', 12],
42965         ['line', 'highway', 'tertiary', 12],
42966         ['line', 'highway', '*', 12],
42967         ['line', 'railway', '*', 12],
42968         ['line', 'waterway', '*', 12],
42969         ['area', 'aeroway', '*', 12],
42970         ['area', 'amenity', '*', 12],
42971         ['area', 'building', '*', 12],
42972         ['area', 'historic', '*', 12],
42973         ['area', 'leisure', '*', 12],
42974         ['area', 'man_made', '*', 12],
42975         ['area', 'natural', '*', 12],
42976         ['area', 'shop', '*', 12],
42977         ['area', 'tourism', '*', 12],
42978         ['area', 'camp_site', '*', 12],
42979         ['point', 'aeroway', '*', 10],
42980         ['point', 'amenity', '*', 10],
42981         ['point', 'building', '*', 10],
42982         ['point', 'historic', '*', 10],
42983         ['point', 'leisure', '*', 10],
42984         ['point', 'man_made', '*', 10],
42985         ['point', 'natural', '*', 10],
42986         ['point', 'shop', '*', 10],
42987         ['point', 'tourism', '*', 10],
42988         ['point', 'camp_site', '*', 10],
42989         ['line', 'name', '*', 12],
42990         ['area', 'name', '*', 12],
42991         ['point', 'name', '*', 10]
42992     ];
42993
42994
42995     function blacklisted(preset) {
42996         var noIcons = ['building', 'landuse', 'natural'];
42997         return lodash.some(noIcons, function(s) {
42998             return preset.id.indexOf(s) >= 0;
42999         });
43000     }
43001
43002
43003     function get(array, prop) {
43004         return function(d, i) { return array[i][prop]; };
43005     }
43006
43007
43008     function textWidth(text$$1, size, elem) {
43009         var c = textWidthCache[size];
43010         if (!c) c = textWidthCache[size] = {};
43011
43012         if (c[text$$1]) {
43013             return c[text$$1];
43014
43015         } else if (elem) {
43016             c[text$$1] = elem.getComputedTextLength();
43017             return c[text$$1];
43018
43019         } else {
43020             var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43021             if (str === null) {
43022                 return size / 3 * 2 * text$$1.length;
43023             } else {
43024                 return size / 3 * (2 * text$$1.length + str.length);
43025             }
43026         }
43027     }
43028
43029
43030     function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43031         var paths = selection$$1.selectAll('path')
43032             .filter(filter)
43033             .data(entities, osmEntity$$1.key);
43034
43035         paths.exit()
43036             .remove();
43037
43038         paths.enter()
43039             .append('path')
43040             .style('stroke-width', get(labels, 'font-size'))
43041             .attr('id', function(d) { return 'labelpath-' + d.id; })
43042             .attr('class', classes)
43043             .merge(paths)
43044             .attr('d', get(labels, 'lineString'));
43045     }
43046
43047
43048     function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43049         var texts = selection$$1.selectAll('text.' + classes)
43050             .filter(filter)
43051             .data(entities, osmEntity$$1.key);
43052
43053         texts.exit()
43054             .remove();
43055
43056         texts.enter()
43057             .append('text')
43058             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43059             .attr('dy', baselineHack ? '0.35em' : null)
43060             .append('textPath')
43061             .attr('class', 'textpath');
43062
43063         texts = selection$$1.selectAll('text.' + classes);
43064
43065         texts.selectAll('.textpath')
43066             .filter(filter)
43067             .data(entities, osmEntity$$1.key)
43068             .attr('startOffset', '50%')
43069             .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43070             .text(utilDisplayNameForPath);
43071     }
43072
43073
43074     function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43075         var texts = selection$$1.selectAll('text.' + classes)
43076             .filter(filter)
43077             .data(entities, osmEntity$$1.key);
43078
43079         texts.exit()
43080             .remove();
43081
43082         texts = texts.enter()
43083             .append('text')
43084             .attr('class', function(d, i) {
43085                 return classes + ' ' + labels[i].classes + ' ' + d.id;
43086             })
43087             .merge(texts);
43088
43089         texts
43090             .attr('x', get(labels, 'x'))
43091             .attr('y', get(labels, 'y'))
43092             .style('text-anchor', get(labels, 'textAnchor'))
43093             .text(utilDisplayName)
43094             .each(function(d, i) {
43095                 textWidth(utilDisplayName(d), labels[i].height, this);
43096             });
43097     }
43098
43099
43100     function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43101         entities = entities.filter(hasText);
43102         labels = labels.filter(hasText);
43103         drawPointLabels(selection$$1, entities, filter, classes, labels);
43104
43105         function hasText(d, i) {
43106             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43107         }
43108     }
43109
43110
43111     function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43112         var icons = selection$$1.selectAll('use.' + classes)
43113             .filter(filter)
43114             .data(entities, osmEntity$$1.key);
43115
43116         icons.exit()
43117             .remove();
43118
43119         icons = icons.enter()
43120             .append('use')
43121             .attr('class', 'icon ' + classes)
43122             .attr('width', '17px')
43123             .attr('height', '17px')
43124             .merge(icons);
43125
43126         icons
43127             .attr('transform', get(labels, 'transform'))
43128             .attr('xlink:href', function(d) {
43129                 var icon = context.presets().match(d, context.graph()).icon;
43130                 return '#' + icon + '-15';
43131             });
43132     }
43133
43134
43135     function drawCollisionBoxes(selection$$1, rtree, which) {
43136         var showDebug = context.getDebug('collision'),
43137             classes = 'debug ' + which + ' ' +
43138                 (which === 'debug-skipped' ? 'orange' : 'yellow');
43139
43140         var debug = selection$$1.selectAll('.layer-label-debug')
43141                 .data(showDebug ? [true] : []);
43142
43143         debug.exit()
43144             .remove();
43145
43146         debug = debug.enter()
43147             .append('g')
43148             .attr('class', 'layer-label-debug')
43149             .merge(debug);
43150
43151         if (showDebug) {
43152             var gj = rtree.all().map(function(d) {
43153                 return { type: 'Polygon', coordinates: [[
43154                     [d.minX, d.minY],
43155                     [d.maxX, d.minY],
43156                     [d.maxX, d.maxY],
43157                     [d.minX, d.maxY],
43158                     [d.minX, d.minY]
43159                 ]]};
43160             });
43161
43162             var debugboxes = debug.selectAll('.' + which)
43163                 .data(gj);
43164
43165             debugboxes.exit()
43166                 .remove();
43167
43168             debugboxes = debugboxes.enter()
43169                 .append('path')
43170                 .attr('class', classes)
43171                 .merge(debugboxes);
43172
43173             debugboxes
43174                 .attr('d', index$4());
43175         }
43176     }
43177
43178
43179     function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43180         var lowZoom = context.surface().classed('low-zoom');
43181
43182         var labelable = [], i, j, k, entity, geometry;
43183         for (i = 0; i < labelStack.length; i++) {
43184             labelable.push([]);
43185         }
43186
43187         if (fullRedraw) {
43188             rdrawn.clear();
43189             rskipped.clear();
43190             entitybboxes = {};
43191         } else {
43192             for (i = 0; i < entities.length; i++) {
43193                 entity = entities[i];
43194                 var toRemove = []
43195                     .concat(entitybboxes[entity.id] || [])
43196                     .concat(entitybboxes[entity.id + 'I'] || []);
43197
43198                 for (j = 0; j < toRemove.length; j++) {
43199                     rdrawn.remove(toRemove[j]);
43200                     rskipped.remove(toRemove[j]);
43201                 }
43202             }
43203         }
43204
43205         // Split entities into groups specified by labelStack
43206         for (i = 0; i < entities.length; i++) {
43207             entity = entities[i];
43208             geometry = entity.geometry(graph);
43209             if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43210
43211             var preset = geometry === 'area' && context.presets().match(entity, graph),
43212                 icon = preset && !blacklisted(preset) && preset.icon;
43213
43214             if (!icon && !utilDisplayName(entity))
43215                 continue;
43216
43217             for (k = 0; k < labelStack.length; k++) {
43218                 var matchGeom = labelStack[k][0],
43219                     matchKey = labelStack[k][1],
43220                     matchVal = labelStack[k][2],
43221                     hasVal = entity.tags[matchKey];
43222
43223                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43224                     labelable[k].push(entity);
43225                     break;
43226                 }
43227             }
43228         }
43229
43230         var positions = {
43231             point: [],
43232             line: [],
43233             area: []
43234         };
43235
43236         var labelled = {
43237             point: [],
43238             line: [],
43239             area: []
43240         };
43241
43242         // Try and find a valid label for labellable entities
43243         for (k = 0; k < labelable.length; k++) {
43244             var fontSize = labelStack[k][3];
43245             for (i = 0; i < labelable[k].length; i++) {
43246                 entity = labelable[k][i];
43247                 geometry = entity.geometry(graph);
43248
43249                 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43250                     name = getName(entity),
43251                     width = name && textWidth(name, fontSize),
43252                     p;
43253
43254                 if (geometry === 'point') {
43255                     p = getPointLabel(entity, width, fontSize, geometry);
43256                 } else if (geometry === 'vertex' && !lowZoom) {
43257                     // don't label vertices at low zoom because they don't have icons
43258                     p = getPointLabel(entity, width, fontSize, geometry);
43259                 } else if (geometry === 'line') {
43260                     p = getLineLabel(entity, width, fontSize);
43261                 } else if (geometry === 'area') {
43262                     p = getAreaLabel(entity, width, fontSize);
43263                 }
43264
43265                 if (p) {
43266                     if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43267                     p.classes = geometry + ' tag-' + labelStack[k][1];
43268                     positions[geometry].push(p);
43269                     labelled[geometry].push(entity);
43270                 }
43271             }
43272         }
43273
43274
43275         function getPointLabel(entity, width, height, geometry) {
43276             var y = (geometry === 'point' ? -12 : 0),
43277                 pointOffsets = {
43278                     ltr: [15, y, 'start'],
43279                     rtl: [-15, y, 'end']
43280                 };
43281
43282             var coord = projection(entity.loc),
43283                 margin = 2,
43284                 offset = pointOffsets[textDirection],
43285                 p = {
43286                     height: height,
43287                     width: width,
43288                     x: coord[0] + offset[0],
43289                     y: coord[1] + offset[1],
43290                     textAnchor: offset[2]
43291                 },
43292                 bbox;
43293
43294             if (textDirection === 'rtl') {
43295                 bbox = {
43296                     minX: p.x - width - margin,
43297                     minY: p.y - (height / 2) - margin,
43298                     maxX: p.x + margin,
43299                     maxY: p.y + (height / 2) + margin
43300                 };
43301             } else {
43302                 bbox = {
43303                     minX: p.x - margin,
43304                     minY: p.y - (height / 2) - margin,
43305                     maxX: p.x + width + margin,
43306                     maxY: p.y + (height / 2) + margin
43307                 };
43308             }
43309
43310             if (tryInsert([bbox], entity.id, true)) {
43311                 return p;
43312             }
43313         }
43314
43315
43316         function getLineLabel(entity, width, height) {
43317             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43318                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
43319                 length = geoPathLength(nodes);
43320
43321             if (length < width + 20) return;
43322
43323             // % along the line to attempt to place the label
43324             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43325                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43326             var margin = 3;
43327
43328             for (var i = 0; i < lineOffsets.length; i++) {
43329                 var offset = lineOffsets[i],
43330                     middle = offset / 100 * length,
43331                     start = middle - width / 2;
43332
43333                 if (start < 0 || start + width > length) continue;
43334
43335                 // generate subpath and ignore paths that are invalid or don't cross viewport.
43336                 var sub = subpath(nodes, start, start + width);
43337                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43338                     continue;
43339                 }
43340
43341                 var isReverse = reverse(sub);
43342                 if (isReverse) {
43343                     sub = sub.reverse();
43344                 }
43345
43346                 var bboxes = [],
43347                     boxsize = (height + 2) / 2;
43348
43349                 for (var j = 0; j < sub.length - 1; j++) {
43350                     var a = sub[j];
43351                     var b = sub[j + 1];
43352                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43353
43354                     for (var box = 0; box < num; box++) {
43355                         var p = geoInterp(a, b, box / num);
43356                         var x0 = p[0] - boxsize - margin;
43357                         var y0 = p[1] - boxsize - margin;
43358                         var x1 = p[0] + boxsize + margin;
43359                         var y1 = p[1] + boxsize + margin;
43360
43361                         bboxes.push({
43362                             minX: Math.min(x0, x1),
43363                             minY: Math.min(y0, y1),
43364                             maxX: Math.max(x0, x1),
43365                             maxY: Math.max(y0, y1)
43366                         });
43367                     }
43368                 }
43369
43370                 if (tryInsert(bboxes, entity.id, false)) {
43371                     return {
43372                         'font-size': height + 2,
43373                         lineString: lineString(sub),
43374                         startOffset: offset + '%'
43375                     };
43376                 }
43377             }
43378
43379             function reverse(p) {
43380                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43381                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43382             }
43383
43384             function lineString(nodes) {
43385                 return 'M' + nodes.join('L');
43386             }
43387
43388             function subpath(nodes, from, to) {
43389                 var sofar = 0,
43390                     start, end, i0, i1;
43391
43392                 for (var i = 0; i < nodes.length - 1; i++) {
43393                     var a = nodes[i],
43394                         b = nodes[i + 1];
43395                     var current = geoEuclideanDistance(a, b);
43396                     var portion;
43397                     if (!start && sofar + current >= from) {
43398                         portion = (from - sofar) / current;
43399                         start = [
43400                             a[0] + portion * (b[0] - a[0]),
43401                             a[1] + portion * (b[1] - a[1])
43402                         ];
43403                         i0 = i + 1;
43404                     }
43405                     if (!end && sofar + current >= to) {
43406                         portion = (to - sofar) / current;
43407                         end = [
43408                             a[0] + portion * (b[0] - a[0]),
43409                             a[1] + portion * (b[1] - a[1])
43410                         ];
43411                         i1 = i + 1;
43412                     }
43413                     sofar += current;
43414                 }
43415
43416                 var ret = nodes.slice(i0, i1);
43417                 ret.unshift(start);
43418                 ret.push(end);
43419                 return ret;
43420             }
43421         }
43422
43423
43424         function getAreaLabel(entity, width, height) {
43425             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
43426                 extent$$1 = entity.extent(graph),
43427                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
43428
43429             if (isNaN(centroid[0]) || entitywidth < 20) return;
43430
43431             var iconSize = 20,
43432                 iconX = centroid[0] - (iconSize / 2),
43433                 iconY = centroid[1] - (iconSize / 2),
43434                 margin = 2,
43435                 textOffset = iconSize + margin,
43436                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
43437
43438             var bbox = {
43439                 minX: iconX,
43440                 minY: iconY,
43441                 maxX: iconX + iconSize,
43442                 maxY: iconY + iconSize
43443             };
43444
43445             // try to add icon
43446             if (tryInsert([bbox], entity.id + 'I', true)) {
43447                 if (width && entitywidth >= width + 20) {
43448                     var labelX = centroid[0],
43449                         labelY = centroid[1] + textOffset;
43450
43451                     bbox = {
43452                         minX: labelX - (width / 2) - margin,
43453                         minY: labelY - (height / 2) - margin,
43454                         maxX: labelX + (width / 2) + margin,
43455                         maxY: labelY + (height / 2) + margin
43456                     };
43457
43458                     // try to add label
43459                     if (tryInsert([bbox], entity.id, true)) {
43460                         p.x = labelX;
43461                         p.y = labelY;
43462                         p.textAnchor = 'middle';
43463                         p.height = height;
43464                     }
43465                 }
43466
43467                 return p;
43468             }
43469         }
43470
43471
43472         function tryInsert(bboxes, id, saveSkipped) {
43473             var skipped = false,
43474                 bbox;
43475
43476             for (var i = 0; i < bboxes.length; i++) {
43477                 bbox = bboxes[i];
43478                 bbox.id = id;
43479
43480                 // Check that label is visible
43481                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
43482                     skipped = true;
43483                     break;
43484                 }
43485                 if (rdrawn.collides(bbox)) {
43486                     skipped = true;
43487                     break;
43488                 }
43489             }
43490
43491             entitybboxes[id] = bboxes;
43492
43493             if (skipped) {
43494                 if (saveSkipped) {
43495                     rskipped.load(bboxes);
43496                 }
43497             } else {
43498                 rdrawn.load(bboxes);
43499             }
43500
43501             return !skipped;
43502         }
43503
43504
43505         var label = selection$$1.selectAll('.layer-label'),
43506             halo = selection$$1.selectAll('.layer-halo');
43507
43508         // points
43509         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
43510         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
43511
43512         // lines
43513         drawLinePaths(halo, labelled.line, filter, '', positions.line);
43514         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
43515         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
43516
43517         // areas
43518         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
43519         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
43520         drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
43521         drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
43522
43523         // debug
43524         drawCollisionBoxes(label, rskipped, 'debug-skipped');
43525         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
43526
43527         selection$$1.call(filterLabels);
43528     }
43529
43530
43531     function filterLabels(selection$$1) {
43532         var layers = selection$$1
43533             .selectAll('.layer-label, .layer-halo');
43534
43535         layers.selectAll('.proximate')
43536             .classed('proximate', false);
43537
43538         var mouse$$1 = context.mouse(),
43539             graph = context.graph(),
43540             selectedIDs = context.selectedIDs(),
43541             ids = [],
43542             pad, bbox;
43543
43544         // hide labels near the mouse
43545         if (mouse$$1) {
43546             pad = 20;
43547             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43548             ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43549         }
43550
43551         // hide labels along selected ways, or near selected vertices
43552         for (var i = 0; i < selectedIDs.length; i++) {
43553             var entity = graph.hasEntity(selectedIDs[i]);
43554             if (!entity) continue;
43555             var geometry = entity.geometry(graph);
43556
43557             if (geometry === 'line') {
43558                 ids.push(selectedIDs[i]);
43559             } else if (geometry === 'vertex') {
43560                 var point = context.projection(entity.loc);
43561                 pad = 10;
43562                 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43563                 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43564             }
43565         }
43566
43567         layers.selectAll(utilEntitySelector(ids))
43568             .classed('proximate', true);
43569     }
43570
43571
43572     var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43573
43574
43575     drawLabels.observe = function(selection$$1) {
43576         var listener = function() { throttleFilterLabels(selection$$1); };
43577         selection$$1.on('mousemove.hidelabels', listener);
43578         context.on('enter.hidelabels', listener);
43579     };
43580
43581
43582     drawLabels.off = function(selection$$1) {
43583         throttleFilterLabels.cancel();
43584         selection$$1.on('mousemove.hidelabels', null);
43585         context.on('enter.hidelabels', null);
43586     };
43587
43588
43589     return drawLabels;
43590 }
43591
43592 // Copies a variable number of methods from source to target.
43593 function utilRebind(target, source) {
43594     var i = 1, n = arguments.length, method;
43595     while (++i < n) {
43596         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
43597     }
43598     return target;
43599 }
43600
43601 // Method is assumed to be a standard D3 getter-setter:
43602 // If passed with no arguments, gets the value.
43603 // If passed with arguments, sets the value and returns the target.
43604 function d3_rebind(target, source, method) {
43605     return function() {
43606         var value = method.apply(source, arguments);
43607         return value === source ? target : value;
43608     };
43609 }
43610
43611 function refresh(selection, node) {
43612     var cr = node.getBoundingClientRect();
43613     var prop = [cr.width, cr.height];
43614     selection.property('__dimensions__', prop);
43615     return prop;
43616 }
43617
43618 function utilGetDimensions(selection, force) {
43619     if (!selection || selection.empty()) {
43620         return [0, 0];
43621     }
43622     var node = selection.node(),
43623         cached = selection.property('__dimensions__');
43624     return (!cached || force) ? refresh(selection, node) : cached;
43625 }
43626
43627
43628 function utilSetDimensions(selection, dimensions) {
43629     if (!selection || selection.empty()) {
43630         return selection;
43631     }
43632     var node = selection.node();
43633     if (dimensions === null) {
43634         refresh(selection, node);
43635         return selection;
43636     }
43637     return selection
43638         .property('__dimensions__', [dimensions[0], dimensions[1]])
43639         .attr('width', dimensions[0])
43640         .attr('height', dimensions[1]);
43641 }
43642
43643 function svgPointTransform(projection) {
43644     return function(entity) {
43645         // http://jsperf.com/short-array-join
43646         var pt = projection(entity.loc);
43647         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43648     };
43649 }
43650
43651 function d3geoTile() {
43652   var size = [960, 500],
43653       scale = 256,
43654       scaleExtent = [0, 20],
43655       translate = [size[0] / 2, size[1] / 2],
43656       zoomDelta = 0;
43657
43658   function bound(_) {
43659       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43660   }
43661
43662   function tile() {
43663     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43664         z0 = bound(Math.round(z + zoomDelta)),
43665         k = Math.pow(2, z - z0 + 8),
43666         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43667         tiles = [],
43668         cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43669         rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43670
43671     rows.forEach(function(y) {
43672       cols.forEach(function(x) {
43673         tiles.push([x, y, z0]);
43674       });
43675     });
43676
43677     tiles.translate = origin;
43678     tiles.scale = k;
43679
43680     return tiles;
43681   }
43682
43683   tile.scaleExtent = function(_) {
43684     if (!arguments.length) return scaleExtent;
43685     scaleExtent = _;
43686     return tile;
43687   };
43688
43689   tile.size = function(_) {
43690     if (!arguments.length) return size;
43691     size = _;
43692     return tile;
43693   };
43694
43695   tile.scale = function(_) {
43696     if (!arguments.length) return scale;
43697     scale = _;
43698     return tile;
43699   };
43700
43701   tile.translate = function(_) {
43702     if (!arguments.length) return translate;
43703     translate = _;
43704     return tile;
43705   };
43706
43707   tile.zoomDelta = function(_) {
43708     if (!arguments.length) return zoomDelta;
43709     zoomDelta = +_;
43710     return tile;
43711   };
43712
43713   return tile;
43714 }
43715
43716 /* global Mapillary:false */
43717 var apibase = 'https://a.mapillary.com/v2/';
43718 var viewercss = 'mapillary-js/mapillary.min.css';
43719 var viewerjs = 'mapillary-js/mapillary.min.js';
43720 var trafficocss = 'traffico/stylesheets/traffico.css';
43721 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43722 var maxResults = 1000;
43723 var tileZoom = 14;
43724 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43725 var mapillaryCache;
43726 var mapillaryClicks;
43727 var mapillaryImage;
43728 var mapillarySignDefs;
43729 var mapillaryViewer;
43730
43731
43732 function abortRequest(i) {
43733     i.abort();
43734 }
43735
43736
43737 function nearNullIsland(x, y, z) {
43738     if (z >= 7) {
43739         var center = Math.pow(2, z - 1),
43740             width = Math.pow(2, z - 6),
43741             min$$1 = center - (width / 2),
43742             max$$1 = center + (width / 2) - 1;
43743         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43744     }
43745     return false;
43746 }
43747
43748
43749 function maxPageAtZoom(z) {
43750     if (z < 15)   return 2;
43751     if (z === 15) return 5;
43752     if (z === 16) return 10;
43753     if (z === 17) return 20;
43754     if (z === 18) return 40;
43755     if (z > 18)   return 80;
43756 }
43757
43758
43759 function getTiles(projection) {
43760     var s = projection.scale() * 2 * Math.PI,
43761         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43762         ts = 256 * Math.pow(2, z - tileZoom),
43763         origin = [
43764             s / 2 - projection.translate()[0],
43765             s / 2 - projection.translate()[1]];
43766
43767     return d3geoTile()
43768         .scaleExtent([tileZoom, tileZoom])
43769         .scale(s)
43770         .size(projection.clipExtent()[1])
43771         .translate(projection.translate())()
43772         .map(function(tile) {
43773             var x = tile[0] * ts - origin[0],
43774                 y = tile[1] * ts - origin[1];
43775
43776             return {
43777                 id: tile.toString(),
43778                 xyz: tile,
43779                 extent: geoExtent$$1(
43780                     projection.invert([x, y + ts]),
43781                     projection.invert([x + ts, y])
43782                 )
43783             };
43784         });
43785 }
43786
43787
43788 function loadTiles(which, url, projection) {
43789     var s = projection.scale() * 2 * Math.PI,
43790         currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43791
43792     var tiles = getTiles(projection).filter(function(t) {
43793             return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43794         });
43795
43796     lodash.filter(which.inflight, function(v, k) {
43797         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43798         if (!wanted) delete which.inflight[k];
43799         return !wanted;
43800     }).map(abortRequest);
43801
43802     tiles.forEach(function(tile) {
43803         loadNextTilePage(which, currZoom, url, tile);
43804     });
43805 }
43806
43807
43808 function loadNextTilePage(which, currZoom, url, tile) {
43809     var cache = mapillaryCache[which],
43810         rect = tile.extent.rectangle(),
43811         maxPages = maxPageAtZoom(currZoom),
43812         nextPage = cache.nextPage[tile.id] || 0;
43813
43814     if (nextPage > maxPages) return;
43815
43816     var id = tile.id + ',' + String(nextPage);
43817     if (cache.loaded[id] || cache.inflight[id]) return;
43818
43819     cache.inflight[id] = json(url +
43820         utilQsString({
43821             geojson: 'true',
43822             limit: maxResults,
43823             page: nextPage,
43824             client_id: clientId,
43825             min_lon: rect[0],
43826             min_lat: rect[1],
43827             max_lon: rect[2],
43828             max_lat: rect[3]
43829         }), function(err, data) {
43830             cache.loaded[id] = true;
43831             delete cache.inflight[id];
43832             if (err || !data.features || !data.features.length) return;
43833
43834             var features = [],
43835                 feature, loc, d;
43836
43837             for (var i = 0; i < data.features.length; i++) {
43838                 feature = data.features[i];
43839                 loc = feature.geometry.coordinates;
43840                 d = { key: feature.properties.key, loc: loc };
43841                 if (which === 'images') d.ca = feature.properties.ca;
43842                 if (which === 'signs') d.signs = feature.properties.rects;
43843
43844                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43845             }
43846
43847             cache.rtree.load(features);
43848
43849             if (which === 'images') dispatch$2.call('loadedImages');
43850             if (which === 'signs') dispatch$2.call('loadedSigns');
43851
43852             if (data.features.length === maxResults) {  // more pages to load
43853                 cache.nextPage[tile.id] = nextPage + 1;
43854                 loadNextTilePage(which, currZoom, url, tile);
43855             } else {
43856                 cache.nextPage[tile.id] = Infinity;     // no more pages to load
43857             }
43858         }
43859     );
43860 }
43861
43862
43863 // partition viewport into `psize` x `psize` regions
43864 function partitionViewport(psize, projection) {
43865     var dimensions = projection.clipExtent()[1];
43866     psize = psize || 16;
43867     var cols = sequence(0, dimensions[0], psize),
43868         rows = sequence(0, dimensions[1], psize),
43869         partitions = [];
43870
43871     rows.forEach(function(y) {
43872         cols.forEach(function(x) {
43873             var min$$1 = [x, y + psize],
43874                 max$$1 = [x + psize, y];
43875             partitions.push(
43876                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43877         });
43878     });
43879
43880     return partitions;
43881 }
43882
43883
43884 // no more than `limit` results per partition.
43885 function searchLimited(psize, limit, projection, rtree) {
43886     limit = limit || 3;
43887
43888     var partitions = partitionViewport(psize, projection);
43889     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43890         return rtree.search(extent$$1.bbox())
43891             .slice(0, limit)
43892             .map(function(d) { return d.data; });
43893     })));
43894 }
43895
43896
43897
43898 var serviceMapillary = {
43899
43900     init: function() {
43901         if (!mapillaryCache) {
43902             this.reset();
43903         }
43904
43905         this.event = utilRebind(this, dispatch$2, 'on');
43906     },
43907
43908     reset: function() {
43909         var cache = mapillaryCache;
43910
43911         if (cache) {
43912             if (cache.images && cache.images.inflight) {
43913                 lodash.forEach(cache.images.inflight, abortRequest);
43914             }
43915             if (cache.signs && cache.signs.inflight) {
43916                 lodash.forEach(cache.signs.inflight, abortRequest);
43917             }
43918         }
43919
43920         mapillaryCache = {
43921             images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() },
43922             signs:  { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() }
43923         };
43924
43925         mapillaryImage = null;
43926         mapillaryClicks = [];
43927     },
43928
43929
43930     images: function(projection) {
43931         var psize = 16, limit = 3;
43932         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43933     },
43934
43935
43936     signs: function(projection) {
43937         var psize = 32, limit = 3;
43938         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43939     },
43940
43941
43942     signsSupported: function() {
43943         var detected = utilDetect();
43944         if (detected.ie) return false;
43945         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43946         return true;
43947     },
43948
43949
43950     signHTML: function(d) {
43951         if (!mapillarySignDefs) return;
43952
43953         var detectionPackage = d.signs[0].package,
43954             type = d.signs[0].type,
43955             country = detectionPackage.split('_')[1];
43956
43957         return mapillarySignDefs[country][type];
43958     },
43959
43960
43961     loadImages: function(projection) {
43962         var url = apibase + 'search/im/geojson?';
43963         loadTiles('images', url, projection);
43964     },
43965
43966
43967     loadSigns: function(context, projection) {
43968         var url = apibase + 'search/im/geojson/or?';
43969         loadTiles('signs', url, projection);
43970
43971         // load traffico css
43972         select('head').selectAll('#traffico')
43973             .data([0])
43974             .enter()
43975             .append('link')
43976             .attr('id', 'traffico')
43977             .attr('rel', 'stylesheet')
43978             .attr('href', context.asset(trafficocss));
43979
43980         // load traffico sign defs
43981         if (!mapillarySignDefs) {
43982             mapillarySignDefs = {};
43983             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
43984                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
43985                     if (err) return;
43986                     if (region === 'de') region = 'eu';
43987                     mapillarySignDefs[region] = data;
43988                 });
43989             });
43990         }
43991     },
43992
43993
43994     loadViewer: function(context) {
43995         var that = this;
43996         var wrap = select('#content').selectAll('.mapillary-wrap')
43997             .data([0]);
43998
43999         var enter = wrap.enter()
44000             .append('div')
44001             .attr('class', 'mapillary-wrap')
44002             .classed('al', true)       // 'al'=left,  'ar'=right
44003             .classed('hidden', true);
44004
44005         enter
44006             .append('button')
44007             .attr('class', 'thumb-hide')
44008             .on('click', function () { that.hideViewer(); })
44009             .append('div')
44010             .call(svgIcon('#icon-close'));
44011
44012         enter
44013             .append('div')
44014             .attr('id', 'mly')
44015             .attr('class', 'mly-wrapper')
44016             .classed('active', false);
44017
44018         // load mapillary-viewercss
44019         select('head').selectAll('#mapillary-viewercss')
44020             .data([0])
44021             .enter()
44022             .append('link')
44023             .attr('id', 'mapillary-viewercss')
44024             .attr('rel', 'stylesheet')
44025             .attr('href', context.asset(viewercss));
44026
44027         // load mapillary-viewerjs
44028         select('head').selectAll('#mapillary-viewerjs')
44029             .data([0])
44030             .enter()
44031             .append('script')
44032             .attr('id', 'mapillary-viewerjs')
44033             .attr('src', context.asset(viewerjs));
44034     },
44035
44036
44037     showViewer: function() {
44038         select('#content')
44039             .selectAll('.mapillary-wrap')
44040             .classed('hidden', false)
44041             .selectAll('.mly-wrapper')
44042             .classed('active', true);
44043
44044         return this;
44045     },
44046
44047
44048     hideViewer: function() {
44049         select('#content')
44050             .selectAll('.mapillary-wrap')
44051             .classed('hidden', true)
44052             .selectAll('.mly-wrapper')
44053             .classed('active', false);
44054
44055         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44056             .classed('selected', false);
44057
44058         mapillaryImage = null;
44059         return this;
44060     },
44061
44062
44063     updateViewer: function(imageKey, context) {
44064         if (!imageKey) return;
44065
44066         if (!mapillaryViewer) {
44067             this.initViewer(imageKey, context);
44068         } else {
44069             mapillaryViewer.moveToKey(imageKey);
44070         }
44071
44072         return this;
44073     },
44074
44075
44076     initViewer: function(imageKey, context) {
44077         var that = this;
44078         if (Mapillary && imageKey) {
44079             var opts = {
44080                 baseImageSize: 320,
44081                 component: {
44082                     cover: false,
44083                     keyboard: false
44084                 }
44085             };
44086
44087             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44088             mapillaryViewer.on('nodechanged', nodeChanged);
44089         }
44090
44091         function nodeChanged(node) {
44092             var clicks = mapillaryClicks;
44093             var index = clicks.indexOf(node.key);
44094             if (index > -1) {    // nodechange initiated from clicking on a marker..
44095                 clicks.splice(index, 1);
44096             } else {             // nodechange initiated from the Mapillary viewer controls..
44097                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44098                 context.map().centerEase(loc);
44099                 that.selectedImage(node.key, false);
44100             }
44101         }
44102     },
44103
44104
44105     selectedImage: function(imageKey, fromClick) {
44106         if (!arguments.length) return mapillaryImage;
44107
44108         mapillaryImage = imageKey;
44109         if (fromClick) {
44110             mapillaryClicks.push(imageKey);
44111         }
44112
44113         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44114             .classed('selected', function(d) { return d.key === imageKey; });
44115
44116         return this;
44117     },
44118
44119
44120     cache: function(_) {
44121         if (!arguments.length) return mapillaryCache;
44122         mapillaryCache = _;
44123         return this;
44124     },
44125
44126
44127     signDefs: function(_) {
44128         if (!arguments.length) return mapillarySignDefs;
44129         mapillarySignDefs = _;
44130         return this;
44131     }
44132
44133 };
44134
44135 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44136 var nominatimCache;
44137
44138
44139 var serviceNominatim = {
44140
44141     init: function() { nominatimCache = index$9(); },
44142     reset: function() { nominatimCache = index$9(); },
44143
44144
44145     countryCode: function (location, callback) {
44146         var countryCodes = nominatimCache.search(
44147             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44148         );
44149
44150         if (countryCodes.length > 0) {
44151             return callback(null, countryCodes[0].data);
44152         }
44153
44154         json(apibase$1 + 'reverse?' +
44155             utilQsString({
44156                 format: 'json',
44157                 addressdetails: 1,
44158                 lat: location[1],
44159                 lon: location[0]
44160             }), function(err, result) {
44161                 if (err)
44162                     return callback(err);
44163                 else if (result && result.error)
44164                     return callback(result.error);
44165
44166                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
44167                 nominatimCache.insert(lodash.assign(extent$$1.bbox(),
44168                     { data: result.address.country_code }
44169                 ));
44170
44171                 callback(null, result.address.country_code);
44172             }
44173         );
44174     },
44175
44176
44177     search: function (val, callback) {
44178         var searchVal = encodeURIComponent(val);
44179         json(apibase$1 + 'search/' + searchVal + '?limit=10&format=json', callback);
44180     }
44181
44182 };
44183
44184 var hashes$1 = createCommonjsModule(function (module, exports) {
44185 /**
44186  * jshashes - https://github.com/h2non/jshashes
44187  * Released under the "New BSD" license
44188  *
44189  * Algorithms specification:
44190  *
44191  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44192  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44193  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44194  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44195  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44196  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44197  */
44198 (function() {
44199   var Hashes;
44200
44201   function utf8Encode(str) {
44202     var x, y, output = '',
44203       i = -1,
44204       l;
44205
44206     if (str && str.length) {
44207       l = str.length;
44208       while ((i += 1) < l) {
44209         /* Decode utf-16 surrogate pairs */
44210         x = str.charCodeAt(i);
44211         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44212         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44213           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44214           i += 1;
44215         }
44216         /* Encode output as utf-8 */
44217         if (x <= 0x7F) {
44218           output += String.fromCharCode(x);
44219         } else if (x <= 0x7FF) {
44220           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44221             0x80 | (x & 0x3F));
44222         } else if (x <= 0xFFFF) {
44223           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44224             0x80 | ((x >>> 6) & 0x3F),
44225             0x80 | (x & 0x3F));
44226         } else if (x <= 0x1FFFFF) {
44227           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44228             0x80 | ((x >>> 12) & 0x3F),
44229             0x80 | ((x >>> 6) & 0x3F),
44230             0x80 | (x & 0x3F));
44231         }
44232       }
44233     }
44234     return output;
44235   }
44236
44237   function utf8Decode(str) {
44238     var i, ac, c1, c2, c3, arr = [],
44239       l;
44240     i = ac = c1 = c2 = c3 = 0;
44241
44242     if (str && str.length) {
44243       l = str.length;
44244       str += '';
44245
44246       while (i < l) {
44247         c1 = str.charCodeAt(i);
44248         ac += 1;
44249         if (c1 < 128) {
44250           arr[ac] = String.fromCharCode(c1);
44251           i += 1;
44252         } else if (c1 > 191 && c1 < 224) {
44253           c2 = str.charCodeAt(i + 1);
44254           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44255           i += 2;
44256         } else {
44257           c2 = str.charCodeAt(i + 1);
44258           c3 = str.charCodeAt(i + 2);
44259           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44260           i += 3;
44261         }
44262       }
44263     }
44264     return arr.join('');
44265   }
44266
44267   /**
44268    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44269    * to work around bugs in some JS interpreters.
44270    */
44271
44272   function safe_add(x, y) {
44273     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44274       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44275     return (msw << 16) | (lsw & 0xFFFF);
44276   }
44277
44278   /**
44279    * Bitwise rotate a 32-bit number to the left.
44280    */
44281
44282   function bit_rol(num, cnt) {
44283     return (num << cnt) | (num >>> (32 - cnt));
44284   }
44285
44286   /**
44287    * Convert a raw string to a hex string
44288    */
44289
44290   function rstr2hex(input, hexcase) {
44291     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44292       output = '',
44293       x, i = 0,
44294       l = input.length;
44295     for (; i < l; i += 1) {
44296       x = input.charCodeAt(i);
44297       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44298     }
44299     return output;
44300   }
44301
44302   /**
44303    * Encode a string as utf-16
44304    */
44305
44306   function binb2rstr(input) {
44307     var i, l = input.length * 32,
44308       output = '';
44309     for (i = 0; i < l; i += 8) {
44310       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44311     }
44312     return output;
44313   }
44314
44315   /**
44316    * Convert an array of little-endian words to a string
44317    */
44318
44319   function binl2rstr(input) {
44320     var i, l = input.length * 32,
44321       output = '';
44322     for (i = 0; i < l; i += 8) {
44323       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44324     }
44325     return output;
44326   }
44327
44328   /**
44329    * Convert a raw string to an array of little-endian words
44330    * Characters >255 have their high-byte silently ignored.
44331    */
44332
44333   function rstr2binl(input) {
44334     var i, l = input.length * 8,
44335       output = Array(input.length >> 2),
44336       lo = output.length;
44337     for (i = 0; i < lo; i += 1) {
44338       output[i] = 0;
44339     }
44340     for (i = 0; i < l; i += 8) {
44341       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44342     }
44343     return output;
44344   }
44345
44346   /**
44347    * Convert a raw string to an array of big-endian words
44348    * Characters >255 have their high-byte silently ignored.
44349    */
44350
44351   function rstr2binb(input) {
44352     var i, l = input.length * 8,
44353       output = Array(input.length >> 2),
44354       lo = output.length;
44355     for (i = 0; i < lo; i += 1) {
44356       output[i] = 0;
44357     }
44358     for (i = 0; i < l; i += 8) {
44359       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44360     }
44361     return output;
44362   }
44363
44364   /**
44365    * Convert a raw string to an arbitrary string encoding
44366    */
44367
44368   function rstr2any(input, encoding) {
44369     var divisor = encoding.length,
44370       remainders = Array(),
44371       i, q, x, ld, quotient, dividend, output, full_length;
44372
44373     /* Convert to an array of 16-bit big-endian values, forming the dividend */
44374     dividend = Array(Math.ceil(input.length / 2));
44375     ld = dividend.length;
44376     for (i = 0; i < ld; i += 1) {
44377       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44378     }
44379
44380     /**
44381      * Repeatedly perform a long division. The binary array forms the dividend,
44382      * the length of the encoding is the divisor. Once computed, the quotient
44383      * forms the dividend for the next step. We stop when the dividend is zerHashes.
44384      * All remainders are stored for later use.
44385      */
44386     while (dividend.length > 0) {
44387       quotient = Array();
44388       x = 0;
44389       for (i = 0; i < dividend.length; i += 1) {
44390         x = (x << 16) + dividend[i];
44391         q = Math.floor(x / divisor);
44392         x -= q * divisor;
44393         if (quotient.length > 0 || q > 0) {
44394           quotient[quotient.length] = q;
44395         }
44396       }
44397       remainders[remainders.length] = x;
44398       dividend = quotient;
44399     }
44400
44401     /* Convert the remainders to the output string */
44402     output = '';
44403     for (i = remainders.length - 1; i >= 0; i--) {
44404       output += encoding.charAt(remainders[i]);
44405     }
44406
44407     /* Append leading zero equivalents */
44408     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
44409     for (i = output.length; i < full_length; i += 1) {
44410       output = encoding[0] + output;
44411     }
44412     return output;
44413   }
44414
44415   /**
44416    * Convert a raw string to a base-64 string
44417    */
44418
44419   function rstr2b64(input, b64pad) {
44420     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44421       output = '',
44422       len = input.length,
44423       i, j, triplet;
44424     b64pad = b64pad || '=';
44425     for (i = 0; i < len; i += 3) {
44426       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44427       for (j = 0; j < 4; j += 1) {
44428         if (i * 8 + j * 6 > input.length * 8) {
44429           output += b64pad;
44430         } else {
44431           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44432         }
44433       }
44434     }
44435     return output;
44436   }
44437
44438   Hashes = {
44439     /**
44440      * @property {String} version
44441      * @readonly
44442      */
44443     VERSION: '1.0.5',
44444     /**
44445      * @member Hashes
44446      * @class Base64
44447      * @constructor
44448      */
44449     Base64: function() {
44450       // private properties
44451       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44452         pad = '=', // default pad according with the RFC standard
44453         url = false, // URL encoding support @todo
44454         utf8 = true; // by default enable UTF-8 support encoding
44455
44456       // public method for encoding
44457       this.encode = function(input) {
44458         var i, j, triplet,
44459           output = '',
44460           len = input.length;
44461
44462         pad = pad || '=';
44463         input = (utf8) ? utf8Encode(input) : input;
44464
44465         for (i = 0; i < len; i += 3) {
44466           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44467           for (j = 0; j < 4; j += 1) {
44468             if (i * 8 + j * 6 > len * 8) {
44469               output += pad;
44470             } else {
44471               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44472             }
44473           }
44474         }
44475         return output;
44476       };
44477
44478       // public method for decoding
44479       this.decode = function(input) {
44480         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
44481         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
44482           dec = '',
44483           arr = [];
44484         if (!input) {
44485           return input;
44486         }
44487
44488         i = ac = 0;
44489         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
44490         //input += '';
44491
44492         do { // unpack four hexets into three octets using index points in b64
44493           h1 = tab.indexOf(input.charAt(i += 1));
44494           h2 = tab.indexOf(input.charAt(i += 1));
44495           h3 = tab.indexOf(input.charAt(i += 1));
44496           h4 = tab.indexOf(input.charAt(i += 1));
44497
44498           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
44499
44500           o1 = bits >> 16 & 0xff;
44501           o2 = bits >> 8 & 0xff;
44502           o3 = bits & 0xff;
44503           ac += 1;
44504
44505           if (h3 === 64) {
44506             arr[ac] = String.fromCharCode(o1);
44507           } else if (h4 === 64) {
44508             arr[ac] = String.fromCharCode(o1, o2);
44509           } else {
44510             arr[ac] = String.fromCharCode(o1, o2, o3);
44511           }
44512         } while (i < input.length);
44513
44514         dec = arr.join('');
44515         dec = (utf8) ? utf8Decode(dec) : dec;
44516
44517         return dec;
44518       };
44519
44520       // set custom pad string
44521       this.setPad = function(str) {
44522         pad = str || pad;
44523         return this;
44524       };
44525       // set custom tab string characters
44526       this.setTab = function(str) {
44527         tab = str || tab;
44528         return this;
44529       };
44530       this.setUTF8 = function(bool) {
44531         if (typeof bool === 'boolean') {
44532           utf8 = bool;
44533         }
44534         return this;
44535       };
44536     },
44537
44538     /**
44539      * CRC-32 calculation
44540      * @member Hashes
44541      * @method CRC32
44542      * @static
44543      * @param {String} str Input String
44544      * @return {String}
44545      */
44546     CRC32: function(str) {
44547       var crc = 0,
44548         x = 0,
44549         y = 0,
44550         table, i, iTop;
44551       str = utf8Encode(str);
44552
44553       table = [
44554         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44555         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44556         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44557         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44558         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44559         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44560         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44561         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44562         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44563         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44564         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44565         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44566         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44567         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44568         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44569         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44570         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44571         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44572         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44573         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44574         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44575         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44576         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44577         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44578         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44579         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44580       ].join('');
44581
44582       crc = crc ^ (-1);
44583       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44584         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44585         x = '0x' + table.substr(y * 9, 8);
44586         crc = (crc >>> 8) ^ x;
44587       }
44588       // always return a positive number (that's what >>> 0 does)
44589       return (crc ^ (-1)) >>> 0;
44590     },
44591     /**
44592      * @member Hashes
44593      * @class MD5
44594      * @constructor
44595      * @param {Object} [config]
44596      *
44597      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44598      * Digest Algorithm, as defined in RFC 1321.
44599      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44600      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44601      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44602      */
44603     MD5: function(options) {
44604       /**
44605        * Private config properties. You may need to tweak these to be compatible with
44606        * the server-side, but the defaults work in most cases.
44607        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44608        */
44609       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44610         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44611         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44612
44613       // privileged (public) methods
44614       this.hex = function(s) {
44615         return rstr2hex(rstr(s, utf8), hexcase);
44616       };
44617       this.b64 = function(s) {
44618         return rstr2b64(rstr(s), b64pad);
44619       };
44620       this.any = function(s, e) {
44621         return rstr2any(rstr(s, utf8), e);
44622       };
44623       this.raw = function(s) {
44624         return rstr(s, utf8);
44625       };
44626       this.hex_hmac = function(k, d) {
44627         return rstr2hex(rstr_hmac(k, d), hexcase);
44628       };
44629       this.b64_hmac = function(k, d) {
44630         return rstr2b64(rstr_hmac(k, d), b64pad);
44631       };
44632       this.any_hmac = function(k, d, e) {
44633         return rstr2any(rstr_hmac(k, d), e);
44634       };
44635       /**
44636        * Perform a simple self-test to see if the VM is working
44637        * @return {String} Hexadecimal hash sample
44638        */
44639       this.vm_test = function() {
44640         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44641       };
44642       /**
44643        * Enable/disable uppercase hexadecimal returned string
44644        * @param {Boolean}
44645        * @return {Object} this
44646        */
44647       this.setUpperCase = function(a) {
44648         if (typeof a === 'boolean') {
44649           hexcase = a;
44650         }
44651         return this;
44652       };
44653       /**
44654        * Defines a base64 pad string
44655        * @param {String} Pad
44656        * @return {Object} this
44657        */
44658       this.setPad = function(a) {
44659         b64pad = a || b64pad;
44660         return this;
44661       };
44662       /**
44663        * Defines a base64 pad string
44664        * @param {Boolean}
44665        * @return {Object} [this]
44666        */
44667       this.setUTF8 = function(a) {
44668         if (typeof a === 'boolean') {
44669           utf8 = a;
44670         }
44671         return this;
44672       };
44673
44674       // private methods
44675
44676       /**
44677        * Calculate the MD5 of a raw string
44678        */
44679
44680       function rstr(s) {
44681         s = (utf8) ? utf8Encode(s) : s;
44682         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44683       }
44684
44685       /**
44686        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44687        */
44688
44689       function rstr_hmac(key, data) {
44690         var bkey, ipad, opad, hash, i;
44691
44692         key = (utf8) ? utf8Encode(key) : key;
44693         data = (utf8) ? utf8Encode(data) : data;
44694         bkey = rstr2binl(key);
44695         if (bkey.length > 16) {
44696           bkey = binl(bkey, key.length * 8);
44697         }
44698
44699         ipad = Array(16), opad = Array(16);
44700         for (i = 0; i < 16; i += 1) {
44701           ipad[i] = bkey[i] ^ 0x36363636;
44702           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44703         }
44704         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44705         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44706       }
44707
44708       /**
44709        * Calculate the MD5 of an array of little-endian words, and a bit length.
44710        */
44711
44712       function binl(x, len) {
44713         var i, olda, oldb, oldc, oldd,
44714           a = 1732584193,
44715           b = -271733879,
44716           c = -1732584194,
44717           d = 271733878;
44718
44719         /* append padding */
44720         x[len >> 5] |= 0x80 << ((len) % 32);
44721         x[(((len + 64) >>> 9) << 4) + 14] = len;
44722
44723         for (i = 0; i < x.length; i += 16) {
44724           olda = a;
44725           oldb = b;
44726           oldc = c;
44727           oldd = d;
44728
44729           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44730           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44731           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44732           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44733           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44734           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44735           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44736           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44737           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44738           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44739           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44740           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44741           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44742           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44743           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44744           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44745
44746           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44747           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44748           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44749           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44750           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44751           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44752           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44753           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44754           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44755           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44756           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44757           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44758           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44759           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44760           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44761           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44762
44763           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44764           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44765           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44766           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44767           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44768           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44769           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44770           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44771           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44772           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44773           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44774           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44775           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44776           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44777           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44778           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44779
44780           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44781           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44782           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44783           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44784           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44785           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44786           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44787           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44788           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44789           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44790           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44791           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44792           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44793           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44794           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44795           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44796
44797           a = safe_add(a, olda);
44798           b = safe_add(b, oldb);
44799           c = safe_add(c, oldc);
44800           d = safe_add(d, oldd);
44801         }
44802         return Array(a, b, c, d);
44803       }
44804
44805       /**
44806        * These functions implement the four basic operations the algorithm uses.
44807        */
44808
44809       function md5_cmn(q, a, b, x, s, t) {
44810         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44811       }
44812
44813       function md5_ff(a, b, c, d, x, s, t) {
44814         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44815       }
44816
44817       function md5_gg(a, b, c, d, x, s, t) {
44818         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44819       }
44820
44821       function md5_hh(a, b, c, d, x, s, t) {
44822         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44823       }
44824
44825       function md5_ii(a, b, c, d, x, s, t) {
44826         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44827       }
44828     },
44829     /**
44830      * @member Hashes
44831      * @class Hashes.SHA1
44832      * @param {Object} [config]
44833      * @constructor
44834      *
44835      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44836      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44837      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44838      * See http://pajhome.org.uk/crypt/md5 for details.
44839      */
44840     SHA1: function(options) {
44841       /**
44842        * Private config properties. You may need to tweak these to be compatible with
44843        * the server-side, but the defaults work in most cases.
44844        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44845        */
44846       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44847         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44848         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44849
44850       // public methods
44851       this.hex = function(s) {
44852         return rstr2hex(rstr(s, utf8), hexcase);
44853       };
44854       this.b64 = function(s) {
44855         return rstr2b64(rstr(s, utf8), b64pad);
44856       };
44857       this.any = function(s, e) {
44858         return rstr2any(rstr(s, utf8), e);
44859       };
44860       this.raw = function(s) {
44861         return rstr(s, utf8);
44862       };
44863       this.hex_hmac = function(k, d) {
44864         return rstr2hex(rstr_hmac(k, d));
44865       };
44866       this.b64_hmac = function(k, d) {
44867         return rstr2b64(rstr_hmac(k, d), b64pad);
44868       };
44869       this.any_hmac = function(k, d, e) {
44870         return rstr2any(rstr_hmac(k, d), e);
44871       };
44872       /**
44873        * Perform a simple self-test to see if the VM is working
44874        * @return {String} Hexadecimal hash sample
44875        * @public
44876        */
44877       this.vm_test = function() {
44878         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44879       };
44880       /**
44881        * @description Enable/disable uppercase hexadecimal returned string
44882        * @param {boolean}
44883        * @return {Object} this
44884        * @public
44885        */
44886       this.setUpperCase = function(a) {
44887         if (typeof a === 'boolean') {
44888           hexcase = a;
44889         }
44890         return this;
44891       };
44892       /**
44893        * @description Defines a base64 pad string
44894        * @param {string} Pad
44895        * @return {Object} this
44896        * @public
44897        */
44898       this.setPad = function(a) {
44899         b64pad = a || b64pad;
44900         return this;
44901       };
44902       /**
44903        * @description Defines a base64 pad string
44904        * @param {boolean}
44905        * @return {Object} this
44906        * @public
44907        */
44908       this.setUTF8 = function(a) {
44909         if (typeof a === 'boolean') {
44910           utf8 = a;
44911         }
44912         return this;
44913       };
44914
44915       // private methods
44916
44917       /**
44918        * Calculate the SHA-512 of a raw string
44919        */
44920
44921       function rstr(s) {
44922         s = (utf8) ? utf8Encode(s) : s;
44923         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44924       }
44925
44926       /**
44927        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44928        */
44929
44930       function rstr_hmac(key, data) {
44931         var bkey, ipad, opad, i, hash;
44932         key = (utf8) ? utf8Encode(key) : key;
44933         data = (utf8) ? utf8Encode(data) : data;
44934         bkey = rstr2binb(key);
44935
44936         if (bkey.length > 16) {
44937           bkey = binb(bkey, key.length * 8);
44938         }
44939         ipad = Array(16), opad = Array(16);
44940         for (i = 0; i < 16; i += 1) {
44941           ipad[i] = bkey[i] ^ 0x36363636;
44942           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44943         }
44944         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44945         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44946       }
44947
44948       /**
44949        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44950        */
44951
44952       function binb(x, len) {
44953         var i, j, t, olda, oldb, oldc, oldd, olde,
44954           w = Array(80),
44955           a = 1732584193,
44956           b = -271733879,
44957           c = -1732584194,
44958           d = 271733878,
44959           e = -1009589776;
44960
44961         /* append padding */
44962         x[len >> 5] |= 0x80 << (24 - len % 32);
44963         x[((len + 64 >> 9) << 4) + 15] = len;
44964
44965         for (i = 0; i < x.length; i += 16) {
44966           olda = a,
44967           oldb = b;
44968           oldc = c;
44969           oldd = d;
44970           olde = e;
44971
44972           for (j = 0; j < 80; j += 1) {
44973             if (j < 16) {
44974               w[j] = x[i + j];
44975             } else {
44976               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
44977             }
44978             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
44979               safe_add(safe_add(e, w[j]), sha1_kt(j)));
44980             e = d;
44981             d = c;
44982             c = bit_rol(b, 30);
44983             b = a;
44984             a = t;
44985           }
44986
44987           a = safe_add(a, olda);
44988           b = safe_add(b, oldb);
44989           c = safe_add(c, oldc);
44990           d = safe_add(d, oldd);
44991           e = safe_add(e, olde);
44992         }
44993         return Array(a, b, c, d, e);
44994       }
44995
44996       /**
44997        * Perform the appropriate triplet combination function for the current
44998        * iteration
44999        */
45000
45001       function sha1_ft(t, b, c, d) {
45002         if (t < 20) {
45003           return (b & c) | ((~b) & d);
45004         }
45005         if (t < 40) {
45006           return b ^ c ^ d;
45007         }
45008         if (t < 60) {
45009           return (b & c) | (b & d) | (c & d);
45010         }
45011         return b ^ c ^ d;
45012       }
45013
45014       /**
45015        * Determine the appropriate additive constant for the current iteration
45016        */
45017
45018       function sha1_kt(t) {
45019         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
45020           (t < 60) ? -1894007588 : -899497514;
45021       }
45022     },
45023     /**
45024      * @class Hashes.SHA256
45025      * @param {config}
45026      *
45027      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45028      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45029      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45030      * See http://pajhome.org.uk/crypt/md5 for details.
45031      * Also http://anmar.eu.org/projects/jssha2/
45032      */
45033     SHA256: function(options) {
45034       /**
45035        * Private properties configuration variables. You may need to tweak these to be compatible with
45036        * the server-side, but the defaults work in most cases.
45037        * @see this.setUpperCase() method
45038        * @see this.setPad() method
45039        */
45040       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
45041         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45042         /* base-64 pad character. Default '=' for strict RFC compliance   */
45043         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45044         /* enable/disable utf8 encoding */
45045         sha256_K;
45046
45047       /* privileged (public) methods */
45048       this.hex = function(s) {
45049         return rstr2hex(rstr(s, utf8));
45050       };
45051       this.b64 = function(s) {
45052         return rstr2b64(rstr(s, utf8), b64pad);
45053       };
45054       this.any = function(s, e) {
45055         return rstr2any(rstr(s, utf8), e);
45056       };
45057       this.raw = function(s) {
45058         return rstr(s, utf8);
45059       };
45060       this.hex_hmac = function(k, d) {
45061         return rstr2hex(rstr_hmac(k, d));
45062       };
45063       this.b64_hmac = function(k, d) {
45064         return rstr2b64(rstr_hmac(k, d), b64pad);
45065       };
45066       this.any_hmac = function(k, d, e) {
45067         return rstr2any(rstr_hmac(k, d), e);
45068       };
45069       /**
45070        * Perform a simple self-test to see if the VM is working
45071        * @return {String} Hexadecimal hash sample
45072        * @public
45073        */
45074       this.vm_test = function() {
45075         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45076       };
45077       /**
45078        * Enable/disable uppercase hexadecimal returned string
45079        * @param {boolean}
45080        * @return {Object} this
45081        * @public
45082        */
45083       this.setUpperCase = function(a) {
45084         if (typeof a === 'boolean') {
45085           hexcase = a;
45086         }
45087         return this;
45088       };
45089       /**
45090        * @description Defines a base64 pad string
45091        * @param {string} Pad
45092        * @return {Object} this
45093        * @public
45094        */
45095       this.setPad = function(a) {
45096         b64pad = a || b64pad;
45097         return this;
45098       };
45099       /**
45100        * Defines a base64 pad string
45101        * @param {boolean}
45102        * @return {Object} this
45103        * @public
45104        */
45105       this.setUTF8 = function(a) {
45106         if (typeof a === 'boolean') {
45107           utf8 = a;
45108         }
45109         return this;
45110       };
45111
45112       // private methods
45113
45114       /**
45115        * Calculate the SHA-512 of a raw string
45116        */
45117
45118       function rstr(s, utf8) {
45119         s = (utf8) ? utf8Encode(s) : s;
45120         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45121       }
45122
45123       /**
45124        * Calculate the HMAC-sha256 of a key and some data (raw strings)
45125        */
45126
45127       function rstr_hmac(key, data) {
45128         key = (utf8) ? utf8Encode(key) : key;
45129         data = (utf8) ? utf8Encode(data) : data;
45130         var hash, i = 0,
45131           bkey = rstr2binb(key),
45132           ipad = Array(16),
45133           opad = Array(16);
45134
45135         if (bkey.length > 16) {
45136           bkey = binb(bkey, key.length * 8);
45137         }
45138
45139         for (; i < 16; i += 1) {
45140           ipad[i] = bkey[i] ^ 0x36363636;
45141           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45142         }
45143
45144         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45145         return binb2rstr(binb(opad.concat(hash), 512 + 256));
45146       }
45147
45148       /*
45149        * Main sha256 function, with its support functions
45150        */
45151
45152       function sha256_S(X, n) {
45153         return (X >>> n) | (X << (32 - n));
45154       }
45155
45156       function sha256_R(X, n) {
45157         return (X >>> n);
45158       }
45159
45160       function sha256_Ch(x, y, z) {
45161         return ((x & y) ^ ((~x) & z));
45162       }
45163
45164       function sha256_Maj(x, y, z) {
45165         return ((x & y) ^ (x & z) ^ (y & z));
45166       }
45167
45168       function sha256_Sigma0256(x) {
45169         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45170       }
45171
45172       function sha256_Sigma1256(x) {
45173         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45174       }
45175
45176       function sha256_Gamma0256(x) {
45177         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45178       }
45179
45180       function sha256_Gamma1256(x) {
45181         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45182       }
45183
45184       sha256_K = [
45185         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45186         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45187         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45188         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45189         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45190         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45191         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45192       ];
45193
45194       function binb(m, l) {
45195         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45196           1359893119, -1694144372, 528734635, 1541459225
45197         ];
45198         var W = new Array(64);
45199         var a, b, c, d, e, f, g, h;
45200         var i, j, T1, T2;
45201
45202         /* append padding */
45203         m[l >> 5] |= 0x80 << (24 - l % 32);
45204         m[((l + 64 >> 9) << 4) + 15] = l;
45205
45206         for (i = 0; i < m.length; i += 16) {
45207           a = HASH[0];
45208           b = HASH[1];
45209           c = HASH[2];
45210           d = HASH[3];
45211           e = HASH[4];
45212           f = HASH[5];
45213           g = HASH[6];
45214           h = HASH[7];
45215
45216           for (j = 0; j < 64; j += 1) {
45217             if (j < 16) {
45218               W[j] = m[j + i];
45219             } else {
45220               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45221                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45222             }
45223
45224             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45225               sha256_K[j]), W[j]);
45226             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45227             h = g;
45228             g = f;
45229             f = e;
45230             e = safe_add(d, T1);
45231             d = c;
45232             c = b;
45233             b = a;
45234             a = safe_add(T1, T2);
45235           }
45236
45237           HASH[0] = safe_add(a, HASH[0]);
45238           HASH[1] = safe_add(b, HASH[1]);
45239           HASH[2] = safe_add(c, HASH[2]);
45240           HASH[3] = safe_add(d, HASH[3]);
45241           HASH[4] = safe_add(e, HASH[4]);
45242           HASH[5] = safe_add(f, HASH[5]);
45243           HASH[6] = safe_add(g, HASH[6]);
45244           HASH[7] = safe_add(h, HASH[7]);
45245         }
45246         return HASH;
45247       }
45248
45249     },
45250
45251     /**
45252      * @class Hashes.SHA512
45253      * @param {config}
45254      *
45255      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45256      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45257      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45258      * See http://pajhome.org.uk/crypt/md5 for details.
45259      */
45260     SHA512: function(options) {
45261       /**
45262        * Private properties configuration variables. You may need to tweak these to be compatible with
45263        * the server-side, but the defaults work in most cases.
45264        * @see this.setUpperCase() method
45265        * @see this.setPad() method
45266        */
45267       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45268         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45269         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45270         /* base-64 pad character. Default '=' for strict RFC compliance   */
45271         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45272         /* enable/disable utf8 encoding */
45273         sha512_k;
45274
45275       /* privileged (public) methods */
45276       this.hex = function(s) {
45277         return rstr2hex(rstr(s));
45278       };
45279       this.b64 = function(s) {
45280         return rstr2b64(rstr(s), b64pad);
45281       };
45282       this.any = function(s, e) {
45283         return rstr2any(rstr(s), e);
45284       };
45285       this.raw = function(s) {
45286         return rstr(s, utf8);
45287       };
45288       this.hex_hmac = function(k, d) {
45289         return rstr2hex(rstr_hmac(k, d));
45290       };
45291       this.b64_hmac = function(k, d) {
45292         return rstr2b64(rstr_hmac(k, d), b64pad);
45293       };
45294       this.any_hmac = function(k, d, e) {
45295         return rstr2any(rstr_hmac(k, d), e);
45296       };
45297       /**
45298        * Perform a simple self-test to see if the VM is working
45299        * @return {String} Hexadecimal hash sample
45300        * @public
45301        */
45302       this.vm_test = function() {
45303         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45304       };
45305       /**
45306        * @description Enable/disable uppercase hexadecimal returned string
45307        * @param {boolean}
45308        * @return {Object} this
45309        * @public
45310        */
45311       this.setUpperCase = function(a) {
45312         if (typeof a === 'boolean') {
45313           hexcase = a;
45314         }
45315         return this;
45316       };
45317       /**
45318        * @description Defines a base64 pad string
45319        * @param {string} Pad
45320        * @return {Object} this
45321        * @public
45322        */
45323       this.setPad = function(a) {
45324         b64pad = a || b64pad;
45325         return this;
45326       };
45327       /**
45328        * @description Defines a base64 pad string
45329        * @param {boolean}
45330        * @return {Object} this
45331        * @public
45332        */
45333       this.setUTF8 = function(a) {
45334         if (typeof a === 'boolean') {
45335           utf8 = a;
45336         }
45337         return this;
45338       };
45339
45340       /* private methods */
45341
45342       /**
45343        * Calculate the SHA-512 of a raw string
45344        */
45345
45346       function rstr(s) {
45347         s = (utf8) ? utf8Encode(s) : s;
45348         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45349       }
45350       /*
45351        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45352        */
45353
45354       function rstr_hmac(key, data) {
45355         key = (utf8) ? utf8Encode(key) : key;
45356         data = (utf8) ? utf8Encode(data) : data;
45357
45358         var hash, i = 0,
45359           bkey = rstr2binb(key),
45360           ipad = Array(32),
45361           opad = Array(32);
45362
45363         if (bkey.length > 32) {
45364           bkey = binb(bkey, key.length * 8);
45365         }
45366
45367         for (; i < 32; i += 1) {
45368           ipad[i] = bkey[i] ^ 0x36363636;
45369           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45370         }
45371
45372         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45373         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45374       }
45375
45376       /**
45377        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45378        */
45379
45380       function binb(x, len) {
45381         var j, i, l,
45382           W = new Array(80),
45383           hash = new Array(16),
45384           //Initial hash values
45385           H = [
45386             new int64(0x6a09e667, -205731576),
45387             new int64(-1150833019, -2067093701),
45388             new int64(0x3c6ef372, -23791573),
45389             new int64(-1521486534, 0x5f1d36f1),
45390             new int64(0x510e527f, -1377402159),
45391             new int64(-1694144372, 0x2b3e6c1f),
45392             new int64(0x1f83d9ab, -79577749),
45393             new int64(0x5be0cd19, 0x137e2179)
45394           ],
45395           T1 = new int64(0, 0),
45396           T2 = new int64(0, 0),
45397           a = new int64(0, 0),
45398           b = new int64(0, 0),
45399           c = new int64(0, 0),
45400           d = new int64(0, 0),
45401           e = new int64(0, 0),
45402           f = new int64(0, 0),
45403           g = new int64(0, 0),
45404           h = new int64(0, 0),
45405           //Temporary variables not specified by the document
45406           s0 = new int64(0, 0),
45407           s1 = new int64(0, 0),
45408           Ch = new int64(0, 0),
45409           Maj = new int64(0, 0),
45410           r1 = new int64(0, 0),
45411           r2 = new int64(0, 0),
45412           r3 = new int64(0, 0);
45413
45414         if (sha512_k === undefined) {
45415           //SHA512 constants
45416           sha512_k = [
45417             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
45418             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
45419             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
45420             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
45421             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
45422             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
45423             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
45424             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
45425             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
45426             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
45427             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
45428             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
45429             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
45430             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
45431             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
45432             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
45433             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
45434             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
45435             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
45436             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
45437             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
45438             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
45439             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
45440             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
45441             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
45442             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
45443             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
45444             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
45445             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
45446             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
45447             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
45448             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
45449             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
45450             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
45451             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
45452             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
45453             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
45454             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
45455             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
45456             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
45457           ];
45458         }
45459
45460         for (i = 0; i < 80; i += 1) {
45461           W[i] = new int64(0, 0);
45462         }
45463
45464         // append padding to the source string. The format is described in the FIPS.
45465         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
45466         x[((len + 128 >> 10) << 5) + 31] = len;
45467         l = x.length;
45468         for (i = 0; i < l; i += 32) { //32 dwords is the block size
45469           int64copy(a, H[0]);
45470           int64copy(b, H[1]);
45471           int64copy(c, H[2]);
45472           int64copy(d, H[3]);
45473           int64copy(e, H[4]);
45474           int64copy(f, H[5]);
45475           int64copy(g, H[6]);
45476           int64copy(h, H[7]);
45477
45478           for (j = 0; j < 16; j += 1) {
45479             W[j].h = x[i + 2 * j];
45480             W[j].l = x[i + 2 * j + 1];
45481           }
45482
45483           for (j = 16; j < 80; j += 1) {
45484             //sigma1
45485             int64rrot(r1, W[j - 2], 19);
45486             int64revrrot(r2, W[j - 2], 29);
45487             int64shr(r3, W[j - 2], 6);
45488             s1.l = r1.l ^ r2.l ^ r3.l;
45489             s1.h = r1.h ^ r2.h ^ r3.h;
45490             //sigma0
45491             int64rrot(r1, W[j - 15], 1);
45492             int64rrot(r2, W[j - 15], 8);
45493             int64shr(r3, W[j - 15], 7);
45494             s0.l = r1.l ^ r2.l ^ r3.l;
45495             s0.h = r1.h ^ r2.h ^ r3.h;
45496
45497             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
45498           }
45499
45500           for (j = 0; j < 80; j += 1) {
45501             //Ch
45502             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45503             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45504
45505             //Sigma1
45506             int64rrot(r1, e, 14);
45507             int64rrot(r2, e, 18);
45508             int64revrrot(r3, e, 9);
45509             s1.l = r1.l ^ r2.l ^ r3.l;
45510             s1.h = r1.h ^ r2.h ^ r3.h;
45511
45512             //Sigma0
45513             int64rrot(r1, a, 28);
45514             int64revrrot(r2, a, 2);
45515             int64revrrot(r3, a, 7);
45516             s0.l = r1.l ^ r2.l ^ r3.l;
45517             s0.h = r1.h ^ r2.h ^ r3.h;
45518
45519             //Maj
45520             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45521             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45522
45523             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45524             int64add(T2, s0, Maj);
45525
45526             int64copy(h, g);
45527             int64copy(g, f);
45528             int64copy(f, e);
45529             int64add(e, d, T1);
45530             int64copy(d, c);
45531             int64copy(c, b);
45532             int64copy(b, a);
45533             int64add(a, T1, T2);
45534           }
45535           int64add(H[0], H[0], a);
45536           int64add(H[1], H[1], b);
45537           int64add(H[2], H[2], c);
45538           int64add(H[3], H[3], d);
45539           int64add(H[4], H[4], e);
45540           int64add(H[5], H[5], f);
45541           int64add(H[6], H[6], g);
45542           int64add(H[7], H[7], h);
45543         }
45544
45545         //represent the hash as an array of 32-bit dwords
45546         for (i = 0; i < 8; i += 1) {
45547           hash[2 * i] = H[i].h;
45548           hash[2 * i + 1] = H[i].l;
45549         }
45550         return hash;
45551       }
45552
45553       //A constructor for 64-bit numbers
45554
45555       function int64(h, l) {
45556         this.h = h;
45557         this.l = l;
45558         //this.toString = int64toString;
45559       }
45560
45561       //Copies src into dst, assuming both are 64-bit numbers
45562
45563       function int64copy(dst, src) {
45564         dst.h = src.h;
45565         dst.l = src.l;
45566       }
45567
45568       //Right-rotates a 64-bit number by shift
45569       //Won't handle cases of shift>=32
45570       //The function revrrot() is for that
45571
45572       function int64rrot(dst, x, shift) {
45573         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45574         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45575       }
45576
45577       //Reverses the dwords of the source and then rotates right by shift.
45578       //This is equivalent to rotation by 32+shift
45579
45580       function int64revrrot(dst, x, shift) {
45581         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45582         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45583       }
45584
45585       //Bitwise-shifts right a 64-bit number by shift
45586       //Won't handle shift>=32, but it's never needed in SHA512
45587
45588       function int64shr(dst, x, shift) {
45589         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45590         dst.h = (x.h >>> shift);
45591       }
45592
45593       //Adds two 64-bit numbers
45594       //Like the original implementation, does not rely on 32-bit operations
45595
45596       function int64add(dst, x, y) {
45597         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45598         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45599         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45600         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45601         dst.l = (w0 & 0xffff) | (w1 << 16);
45602         dst.h = (w2 & 0xffff) | (w3 << 16);
45603       }
45604
45605       //Same, except with 4 addends. Works faster than adding them one by one.
45606
45607       function int64add4(dst, a, b, c, d) {
45608         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45609         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45610         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45611         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45612         dst.l = (w0 & 0xffff) | (w1 << 16);
45613         dst.h = (w2 & 0xffff) | (w3 << 16);
45614       }
45615
45616       //Same, except with 5 addends
45617
45618       function int64add5(dst, a, b, c, d, e) {
45619         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45620           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45621           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45622           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45623         dst.l = (w0 & 0xffff) | (w1 << 16);
45624         dst.h = (w2 & 0xffff) | (w3 << 16);
45625       }
45626     },
45627     /**
45628      * @class Hashes.RMD160
45629      * @constructor
45630      * @param {Object} [config]
45631      *
45632      * A JavaScript implementation of the RIPEMD-160 Algorithm
45633      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45634      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45635      * See http://pajhome.org.uk/crypt/md5 for details.
45636      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45637      */
45638     RMD160: function(options) {
45639       /**
45640        * Private properties configuration variables. You may need to tweak these to be compatible with
45641        * the server-side, but the defaults work in most cases.
45642        * @see this.setUpperCase() method
45643        * @see this.setPad() method
45644        */
45645       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45646         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45647         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45648         /* base-64 pad character. Default '=' for strict RFC compliance   */
45649         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45650         /* enable/disable utf8 encoding */
45651         rmd160_r1 = [
45652           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45653           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45654           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45655           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45656           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45657         ],
45658         rmd160_r2 = [
45659           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45660           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45661           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45662           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45663           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45664         ],
45665         rmd160_s1 = [
45666           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45667           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45668           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45669           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45670           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45671         ],
45672         rmd160_s2 = [
45673           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45674           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45675           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45676           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45677           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45678         ];
45679
45680       /* privileged (public) methods */
45681       this.hex = function(s) {
45682         return rstr2hex(rstr(s, utf8));
45683       };
45684       this.b64 = function(s) {
45685         return rstr2b64(rstr(s, utf8), b64pad);
45686       };
45687       this.any = function(s, e) {
45688         return rstr2any(rstr(s, utf8), e);
45689       };
45690       this.raw = function(s) {
45691         return rstr(s, utf8);
45692       };
45693       this.hex_hmac = function(k, d) {
45694         return rstr2hex(rstr_hmac(k, d));
45695       };
45696       this.b64_hmac = function(k, d) {
45697         return rstr2b64(rstr_hmac(k, d), b64pad);
45698       };
45699       this.any_hmac = function(k, d, e) {
45700         return rstr2any(rstr_hmac(k, d), e);
45701       };
45702       /**
45703        * Perform a simple self-test to see if the VM is working
45704        * @return {String} Hexadecimal hash sample
45705        * @public
45706        */
45707       this.vm_test = function() {
45708         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45709       };
45710       /**
45711        * @description Enable/disable uppercase hexadecimal returned string
45712        * @param {boolean}
45713        * @return {Object} this
45714        * @public
45715        */
45716       this.setUpperCase = function(a) {
45717         if (typeof a === 'boolean') {
45718           hexcase = a;
45719         }
45720         return this;
45721       };
45722       /**
45723        * @description Defines a base64 pad string
45724        * @param {string} Pad
45725        * @return {Object} this
45726        * @public
45727        */
45728       this.setPad = function(a) {
45729         if (typeof a !== 'undefined') {
45730           b64pad = a;
45731         }
45732         return this;
45733       };
45734       /**
45735        * @description Defines a base64 pad string
45736        * @param {boolean}
45737        * @return {Object} this
45738        * @public
45739        */
45740       this.setUTF8 = function(a) {
45741         if (typeof a === 'boolean') {
45742           utf8 = a;
45743         }
45744         return this;
45745       };
45746
45747       /* private methods */
45748
45749       /**
45750        * Calculate the rmd160 of a raw string
45751        */
45752
45753       function rstr(s) {
45754         s = (utf8) ? utf8Encode(s) : s;
45755         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45756       }
45757
45758       /**
45759        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45760        */
45761
45762       function rstr_hmac(key, data) {
45763         key = (utf8) ? utf8Encode(key) : key;
45764         data = (utf8) ? utf8Encode(data) : data;
45765         var i, hash,
45766           bkey = rstr2binl(key),
45767           ipad = Array(16),
45768           opad = Array(16);
45769
45770         if (bkey.length > 16) {
45771           bkey = binl(bkey, key.length * 8);
45772         }
45773
45774         for (i = 0; i < 16; i += 1) {
45775           ipad[i] = bkey[i] ^ 0x36363636;
45776           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45777         }
45778         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45779         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45780       }
45781
45782       /**
45783        * Convert an array of little-endian words to a string
45784        */
45785
45786       function binl2rstr(input) {
45787         var i, output = '',
45788           l = input.length * 32;
45789         for (i = 0; i < l; i += 8) {
45790           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45791         }
45792         return output;
45793       }
45794
45795       /**
45796        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45797        */
45798
45799       function binl(x, len) {
45800         var T, j, i, l,
45801           h0 = 0x67452301,
45802           h1 = 0xefcdab89,
45803           h2 = 0x98badcfe,
45804           h3 = 0x10325476,
45805           h4 = 0xc3d2e1f0,
45806           A1, B1, C1, D1, E1,
45807           A2, B2, C2, D2, E2;
45808
45809         /* append padding */
45810         x[len >> 5] |= 0x80 << (len % 32);
45811         x[(((len + 64) >>> 9) << 4) + 14] = len;
45812         l = x.length;
45813
45814         for (i = 0; i < l; i += 16) {
45815           A1 = A2 = h0;
45816           B1 = B2 = h1;
45817           C1 = C2 = h2;
45818           D1 = D2 = h3;
45819           E1 = E2 = h4;
45820           for (j = 0; j <= 79; j += 1) {
45821             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45822             T = safe_add(T, x[i + rmd160_r1[j]]);
45823             T = safe_add(T, rmd160_K1(j));
45824             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45825             A1 = E1;
45826             E1 = D1;
45827             D1 = bit_rol(C1, 10);
45828             C1 = B1;
45829             B1 = T;
45830             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45831             T = safe_add(T, x[i + rmd160_r2[j]]);
45832             T = safe_add(T, rmd160_K2(j));
45833             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45834             A2 = E2;
45835             E2 = D2;
45836             D2 = bit_rol(C2, 10);
45837             C2 = B2;
45838             B2 = T;
45839           }
45840
45841           T = safe_add(h1, safe_add(C1, D2));
45842           h1 = safe_add(h2, safe_add(D1, E2));
45843           h2 = safe_add(h3, safe_add(E1, A2));
45844           h3 = safe_add(h4, safe_add(A1, B2));
45845           h4 = safe_add(h0, safe_add(B1, C2));
45846           h0 = T;
45847         }
45848         return [h0, h1, h2, h3, h4];
45849       }
45850
45851       // specific algorithm methods
45852
45853       function rmd160_f(j, x, y, z) {
45854         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45855           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45856           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45857           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45858           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45859           'rmd160_f: j out of range';
45860       }
45861
45862       function rmd160_K1(j) {
45863         return (0 <= j && j <= 15) ? 0x00000000 :
45864           (16 <= j && j <= 31) ? 0x5a827999 :
45865           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45866           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45867           (64 <= j && j <= 79) ? 0xa953fd4e :
45868           'rmd160_K1: j out of range';
45869       }
45870
45871       function rmd160_K2(j) {
45872         return (0 <= j && j <= 15) ? 0x50a28be6 :
45873           (16 <= j && j <= 31) ? 0x5c4dd124 :
45874           (32 <= j && j <= 47) ? 0x6d703ef3 :
45875           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45876           (64 <= j && j <= 79) ? 0x00000000 :
45877           'rmd160_K2: j out of range';
45878       }
45879     }
45880   };
45881
45882   // exposes Hashes
45883   (function(window, undefined) {
45884     var freeExports = false;
45885     {
45886       freeExports = exports;
45887       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45888         window = commonjsGlobal;
45889       }
45890     }
45891
45892     if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
45893       // define as an anonymous module, so, through path mapping, it can be aliased
45894       undefined(function() {
45895         return Hashes;
45896       });
45897     } else if (freeExports) {
45898       // in Node.js or RingoJS v0.8.0+
45899       if ('object' === 'object' && module && module.exports === freeExports) {
45900         module.exports = Hashes;
45901       }
45902       // in Narwhal or RingoJS v0.7.0-
45903       else {
45904         freeExports.Hashes = Hashes;
45905       }
45906     } else {
45907       // in a browser or Rhino
45908       window.Hashes = Hashes;
45909     }
45910   }(this));
45911 }()); // IIFE
45912 });
45913
45914 var immutable = extend$2;
45915
45916 var hasOwnProperty = Object.prototype.hasOwnProperty;
45917
45918 function extend$2() {
45919     var target = {};
45920
45921     for (var i = 0; i < arguments.length; i++) {
45922         var source = arguments[i];
45923
45924         for (var key in source) {
45925             if (hasOwnProperty.call(source, key)) {
45926                 target[key] = source[key];
45927             }
45928         }
45929     }
45930
45931     return target
45932 }
45933
45934 var hashes = hashes$1;
45935 var xtend$1 = immutable;
45936 var sha1 = new hashes.SHA1();
45937
45938 var ohauth$1 = {};
45939
45940 ohauth$1.qsString = function(obj) {
45941     return Object.keys(obj).sort().map(function(key) {
45942         return ohauth$1.percentEncode(key) + '=' +
45943             ohauth$1.percentEncode(obj[key]);
45944     }).join('&');
45945 };
45946
45947 ohauth$1.stringQs = function(str) {
45948     return str.split('&').filter(function (pair) {
45949         return pair !== '';
45950     }).reduce(function(obj, pair){
45951         var parts = pair.split('=');
45952         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45953             '' : decodeURIComponent(parts[1]);
45954         return obj;
45955     }, {});
45956 };
45957
45958 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45959     var xhr = new XMLHttpRequest(),
45960         twoHundred = /^20\d$/;
45961     xhr.onreadystatechange = function() {
45962         if (4 === xhr.readyState && 0 !== xhr.status) {
45963             if (twoHundred.test(xhr.status)) callback(null, xhr);
45964             else return callback(xhr, null);
45965         }
45966     };
45967     xhr.onerror = function(e) { return callback(e, null); };
45968     xhr.open(method, url, true);
45969     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45970     xhr.send(data);
45971     return xhr;
45972 };
45973
45974 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
45975     var headers = (options && options.header) || {
45976         'Content-Type': 'application/x-www-form-urlencoded'
45977     };
45978     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
45979     return ohauth$1.rawxhr(method, url, data, headers, callback);
45980 };
45981
45982 ohauth$1.nonce = function() {
45983     for (var o = ''; o.length < 6;) {
45984         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
45985     }
45986     return o;
45987 };
45988
45989 ohauth$1.authHeader = function(obj) {
45990     return Object.keys(obj).sort().map(function(key) {
45991         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
45992     }).join(', ');
45993 };
45994
45995 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
45996
45997 ohauth$1.percentEncode = function(s) {
45998     return encodeURIComponent(s)
45999         .replace(/\!/g, '%21').replace(/\'/g, '%27')
46000         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
46001 };
46002
46003 ohauth$1.baseString = function(method, url, params) {
46004     if (params.oauth_signature) delete params.oauth_signature;
46005     return [
46006         method,
46007         ohauth$1.percentEncode(url),
46008         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
46009 };
46010
46011 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
46012     return sha1.b64_hmac(
46013         ohauth$1.percentEncode(oauth_secret) + '&' +
46014         ohauth$1.percentEncode(token_secret),
46015         baseString);
46016 };
46017
46018 /**
46019  * Takes an options object for configuration (consumer_key,
46020  * consumer_secret, version, signature_method, token, token_secret)
46021  * and returns a function that generates the Authorization header
46022  * for given data.
46023  *
46024  * The returned function takes these parameters:
46025  * - method: GET/POST/...
46026  * - uri: full URI with protocol, port, path and query string
46027  * - extra_params: any extra parameters (that are passed in the POST data),
46028  *   can be an object or a from-urlencoded string.
46029  *
46030  * Returned function returns full OAuth header with "OAuth" string in it.
46031  */
46032
46033 ohauth$1.headerGenerator = function(options) {
46034     options = options || {};
46035     var consumer_key = options.consumer_key || '',
46036         consumer_secret = options.consumer_secret || '',
46037         signature_method = options.signature_method || 'HMAC-SHA1',
46038         version = options.version || '1.0',
46039         token = options.token || '',
46040         token_secret = options.token_secret || '';
46041
46042     return function(method, uri, extra_params) {
46043         method = method.toUpperCase();
46044         if (typeof extra_params === 'string' && extra_params.length > 0) {
46045             extra_params = ohauth$1.stringQs(extra_params);
46046         }
46047
46048         var uri_parts = uri.split('?', 2),
46049         base_uri = uri_parts[0];
46050
46051         var query_params = uri_parts.length === 2 ?
46052             ohauth$1.stringQs(uri_parts[1]) : {};
46053
46054         var oauth_params = {
46055             oauth_consumer_key: consumer_key,
46056             oauth_signature_method: signature_method,
46057             oauth_version: version,
46058             oauth_timestamp: ohauth$1.timestamp(),
46059             oauth_nonce: ohauth$1.nonce()
46060         };
46061
46062         if (token) oauth_params.oauth_token = token;
46063
46064         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
46065             base_str = ohauth$1.baseString(method, base_uri, all_params);
46066
46067         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
46068
46069         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
46070     };
46071 };
46072
46073 var index$13 = ohauth$1;
46074
46075 var store$1 = createCommonjsModule(function (module, exports) {
46076 "use strict"
46077 // Module export pattern from
46078 // https://github.com/umdjs/umd/blob/master/returnExports.js
46079 ;(function (root, factory) {
46080     if (typeof undefined === 'function' && undefined.amd) {
46081         // AMD. Register as an anonymous module.
46082         undefined([], factory);
46083     } else {
46084         // Node. Does not work with strict CommonJS, but
46085         // only CommonJS-like environments that support module.exports,
46086         // like Node.
46087         module.exports = factory();
46088     }
46089 }(commonjsGlobal, function () {
46090         
46091         // Store.js
46092         var store = {},
46093                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
46094                 doc = win.document,
46095                 localStorageName = 'localStorage',
46096                 scriptTag = 'script',
46097                 storage;
46098
46099         store.disabled = false;
46100         store.version = '1.3.20';
46101         store.set = function(key, value) {};
46102         store.get = function(key, defaultVal) {};
46103         store.has = function(key) { return store.get(key) !== undefined };
46104         store.remove = function(key) {};
46105         store.clear = function() {};
46106         store.transact = function(key, defaultVal, transactionFn) {
46107                 if (transactionFn == null) {
46108                         transactionFn = defaultVal;
46109                         defaultVal = null;
46110                 }
46111                 if (defaultVal == null) {
46112                         defaultVal = {};
46113                 }
46114                 var val = store.get(key, defaultVal);
46115                 transactionFn(val);
46116                 store.set(key, val);
46117         };
46118         store.getAll = function() {};
46119         store.forEach = function() {};
46120
46121         store.serialize = function(value) {
46122                 return JSON.stringify(value)
46123         };
46124         store.deserialize = function(value) {
46125                 if (typeof value != 'string') { return undefined }
46126                 try { return JSON.parse(value) }
46127                 catch(e) { return value || undefined }
46128         };
46129
46130         // Functions to encapsulate questionable FireFox 3.6.13 behavior
46131         // when about.config::dom.storage.enabled === false
46132         // See https://github.com/marcuswestin/store.js/issues#issue/13
46133         function isLocalStorageNameSupported() {
46134                 try { return (localStorageName in win && win[localStorageName]) }
46135                 catch(err) { return false }
46136         }
46137
46138         if (isLocalStorageNameSupported()) {
46139                 storage = win[localStorageName];
46140                 store.set = function(key, val) {
46141                         if (val === undefined) { return store.remove(key) }
46142                         storage.setItem(key, store.serialize(val));
46143                         return val
46144                 };
46145                 store.get = function(key, defaultVal) {
46146                         var val = store.deserialize(storage.getItem(key));
46147                         return (val === undefined ? defaultVal : val)
46148                 };
46149                 store.remove = function(key) { storage.removeItem(key); };
46150                 store.clear = function() { storage.clear(); };
46151                 store.getAll = function() {
46152                         var ret = {};
46153                         store.forEach(function(key, val) {
46154                                 ret[key] = val;
46155                         });
46156                         return ret
46157                 };
46158                 store.forEach = function(callback) {
46159                         for (var i=0; i<storage.length; i++) {
46160                                 var key = storage.key(i);
46161                                 callback(key, store.get(key));
46162                         }
46163                 };
46164         } else if (doc && doc.documentElement.addBehavior) {
46165                 var storageOwner,
46166                         storageContainer;
46167                 // Since #userData storage applies only to specific paths, we need to
46168                 // somehow link our data to a specific path.  We choose /favicon.ico
46169                 // as a pretty safe option, since all browsers already make a request to
46170                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
46171                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
46172                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
46173                 // since the iframe access rules appear to allow direct access and
46174                 // manipulation of the document element, even for a 404 page.  This
46175                 // document can be used instead of the current document (which would
46176                 // have been limited to the current path) to perform #userData storage.
46177                 try {
46178                         storageContainer = new ActiveXObject('htmlfile');
46179                         storageContainer.open();
46180                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
46181                         storageContainer.close();
46182                         storageOwner = storageContainer.w.frames[0].document;
46183                         storage = storageOwner.createElement('div');
46184                 } catch(e) {
46185                         // somehow ActiveXObject instantiation failed (perhaps some special
46186                         // security settings or otherwse), fall back to per-path storage
46187                         storage = doc.createElement('div');
46188                         storageOwner = doc.body;
46189                 }
46190                 var withIEStorage = function(storeFunction) {
46191                         return function() {
46192                                 var args = Array.prototype.slice.call(arguments, 0);
46193                                 args.unshift(storage);
46194                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
46195                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
46196                                 storageOwner.appendChild(storage);
46197                                 storage.addBehavior('#default#userData');
46198                                 storage.load(localStorageName);
46199                                 var result = storeFunction.apply(store, args);
46200                                 storageOwner.removeChild(storage);
46201                                 return result
46202                         }
46203                 };
46204
46205                 // In IE7, keys cannot start with a digit or contain certain chars.
46206                 // See https://github.com/marcuswestin/store.js/issues/40
46207                 // See https://github.com/marcuswestin/store.js/issues/83
46208                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
46209                 var ieKeyFix = function(key) {
46210                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
46211                 };
46212                 store.set = withIEStorage(function(storage, key, val) {
46213                         key = ieKeyFix(key);
46214                         if (val === undefined) { return store.remove(key) }
46215                         storage.setAttribute(key, store.serialize(val));
46216                         storage.save(localStorageName);
46217                         return val
46218                 });
46219                 store.get = withIEStorage(function(storage, key, defaultVal) {
46220                         key = ieKeyFix(key);
46221                         var val = store.deserialize(storage.getAttribute(key));
46222                         return (val === undefined ? defaultVal : val)
46223                 });
46224                 store.remove = withIEStorage(function(storage, key) {
46225                         key = ieKeyFix(key);
46226                         storage.removeAttribute(key);
46227                         storage.save(localStorageName);
46228                 });
46229                 store.clear = withIEStorage(function(storage) {
46230                         var attributes = storage.XMLDocument.documentElement.attributes;
46231                         storage.load(localStorageName);
46232                         for (var i=attributes.length-1; i>=0; i--) {
46233                                 storage.removeAttribute(attributes[i].name);
46234                         }
46235                         storage.save(localStorageName);
46236                 });
46237                 store.getAll = function(storage) {
46238                         var ret = {};
46239                         store.forEach(function(key, val) {
46240                                 ret[key] = val;
46241                         });
46242                         return ret
46243                 };
46244                 store.forEach = withIEStorage(function(storage, callback) {
46245                         var attributes = storage.XMLDocument.documentElement.attributes;
46246                         for (var i=0, attr; attr=attributes[i]; ++i) {
46247                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
46248                         }
46249                 });
46250         }
46251
46252         try {
46253                 var testKey = '__storejs__';
46254                 store.set(testKey, testKey);
46255                 if (store.get(testKey) != testKey) { store.disabled = true; }
46256                 store.remove(testKey);
46257         } catch(e) {
46258                 store.disabled = true;
46259         }
46260         store.enabled = !store.disabled;
46261         
46262         return store
46263 }));
46264 });
46265
46266 var ohauth = index$13;
46267 var xtend = immutable;
46268 var store = store$1;
46269
46270 // # osm-auth
46271 //
46272 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
46273 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
46274 // does not support custom headers, which this uses everywhere.
46275 var index$12 = function(o) {
46276
46277     var oauth = {};
46278
46279     // authenticated users will also have a request token secret, but it's
46280     // not used in transactions with the server
46281     oauth.authenticated = function() {
46282         return !!(token('oauth_token') && token('oauth_token_secret'));
46283     };
46284
46285     oauth.logout = function() {
46286         token('oauth_token', '');
46287         token('oauth_token_secret', '');
46288         token('oauth_request_token_secret', '');
46289         return oauth;
46290     };
46291
46292     // TODO: detect lack of click event
46293     oauth.authenticate = function(callback) {
46294         if (oauth.authenticated()) return callback();
46295
46296         oauth.logout();
46297
46298         // ## Getting a request token
46299         var params = timenonce(getAuth(o)),
46300             url = o.url + '/oauth/request_token';
46301
46302         params.oauth_signature = ohauth.signature(
46303             o.oauth_secret, '',
46304             ohauth.baseString('POST', url, params));
46305
46306         if (!o.singlepage) {
46307             // Create a 600x550 popup window in the center of the screen
46308             var w = 600, h = 550,
46309                 settings = [
46310                     ['width', w], ['height', h],
46311                     ['left', screen.width / 2 - w / 2],
46312                     ['top', screen.height / 2 - h / 2]].map(function(x) {
46313                         return x.join('=');
46314                     }).join(','),
46315                 popup = window.open('about:blank', 'oauth_window', settings);
46316         }
46317
46318         // Request a request token. When this is complete, the popup
46319         // window is redirected to OSM's authorization page.
46320         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
46321         o.loading();
46322
46323         function reqTokenDone(err, xhr) {
46324             o.done();
46325             if (err) return callback(err);
46326             var resp = ohauth.stringQs(xhr.response);
46327             token('oauth_request_token_secret', resp.oauth_token_secret);
46328             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
46329                 oauth_token: resp.oauth_token,
46330                 oauth_callback: location.href.replace('index.html', '')
46331                     .replace(/#.*/, '').replace(location.search, '') + o.landing
46332             });
46333
46334             if (o.singlepage) {
46335                 location.href = authorize_url;
46336             } else {
46337                 popup.location = authorize_url;
46338             }
46339         }
46340
46341         // Called by a function in a landing page, in the popup window. The
46342         // window closes itself.
46343         window.authComplete = function(token) {
46344             var oauth_token = ohauth.stringQs(token.split('?')[1]);
46345             get_access_token(oauth_token.oauth_token);
46346             delete window.authComplete;
46347         };
46348
46349         // ## Getting an request token
46350         //
46351         // At this point we have an `oauth_token`, brought in from a function
46352         // call on a landing page popup.
46353         function get_access_token(oauth_token) {
46354             var url = o.url + '/oauth/access_token',
46355                 params = timenonce(getAuth(o)),
46356                 request_token_secret = token('oauth_request_token_secret');
46357             params.oauth_token = oauth_token;
46358             params.oauth_signature = ohauth.signature(
46359                 o.oauth_secret,
46360                 request_token_secret,
46361                 ohauth.baseString('POST', url, params));
46362
46363             // ## Getting an access token
46364             //
46365             // The final token required for authentication. At this point
46366             // we have a `request token secret`
46367             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46368             o.loading();
46369         }
46370
46371         function accessTokenDone(err, xhr) {
46372             o.done();
46373             if (err) return callback(err);
46374             var access_token = ohauth.stringQs(xhr.response);
46375             token('oauth_token', access_token.oauth_token);
46376             token('oauth_token_secret', access_token.oauth_token_secret);
46377             callback(null, oauth);
46378         }
46379     };
46380
46381     oauth.bootstrapToken = function(oauth_token, callback) {
46382         // ## Getting an request token
46383         // At this point we have an `oauth_token`, brought in from a function
46384         // call on a landing page popup.
46385         function get_access_token(oauth_token) {
46386             var url = o.url + '/oauth/access_token',
46387                 params = timenonce(getAuth(o)),
46388                 request_token_secret = token('oauth_request_token_secret');
46389             params.oauth_token = oauth_token;
46390             params.oauth_signature = ohauth.signature(
46391                 o.oauth_secret,
46392                 request_token_secret,
46393                 ohauth.baseString('POST', url, params));
46394
46395             // ## Getting an access token
46396             // The final token required for authentication. At this point
46397             // we have a `request token secret`
46398             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46399             o.loading();
46400         }
46401
46402         function accessTokenDone(err, xhr) {
46403             o.done();
46404             if (err) return callback(err);
46405             var access_token = ohauth.stringQs(xhr.response);
46406             token('oauth_token', access_token.oauth_token);
46407             token('oauth_token_secret', access_token.oauth_token_secret);
46408             callback(null, oauth);
46409         }
46410
46411         get_access_token(oauth_token);
46412     };
46413
46414     // # xhr
46415     //
46416     // A single XMLHttpRequest wrapper that does authenticated calls if the
46417     // user has logged in.
46418     oauth.xhr = function(options, callback) {
46419         if (!oauth.authenticated()) {
46420             if (o.auto) {
46421                 return oauth.authenticate(run);
46422             } else {
46423                 callback('not authenticated', null);
46424                 return;
46425             }
46426         } else {
46427             return run();
46428         }
46429
46430         function run() {
46431             var params = timenonce(getAuth(o)),
46432                 oauth_token_secret = token('oauth_token_secret'),
46433                 url = (options.prefix !== false) ? o.url + options.path : options.path,
46434                 url_parts = url.replace(/#.*$/, '').split('?', 2),
46435                 base_url = url_parts[0],
46436                 query = (url_parts.length === 2) ? url_parts[1] : '';
46437
46438             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
46439             if ((!options.options || !options.options.header ||
46440                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
46441                 options.content) {
46442                 params = xtend(params, ohauth.stringQs(options.content));
46443             }
46444
46445             params.oauth_token = token('oauth_token');
46446             params.oauth_signature = ohauth.signature(
46447                 o.oauth_secret,
46448                 oauth_token_secret,
46449                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
46450             );
46451
46452             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
46453         }
46454
46455         function done(err, xhr) {
46456             if (err) return callback(err);
46457             else if (xhr.responseXML) return callback(err, xhr.responseXML);
46458             else return callback(err, xhr.response);
46459         }
46460     };
46461
46462     // pre-authorize this object, if we can just get a token and token_secret
46463     // from the start
46464     oauth.preauth = function(c) {
46465         if (!c) return;
46466         if (c.oauth_token) token('oauth_token', c.oauth_token);
46467         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
46468         return oauth;
46469     };
46470
46471     oauth.options = function(_) {
46472         if (!arguments.length) return o;
46473
46474         o = _;
46475         o.url = o.url || 'http://www.openstreetmap.org';
46476         o.landing = o.landing || 'land.html';
46477         o.singlepage = o.singlepage || false;
46478
46479         // Optional loading and loading-done functions for nice UI feedback.
46480         // by default, no-ops
46481         o.loading = o.loading || function() {};
46482         o.done = o.done || function() {};
46483
46484         return oauth.preauth(o);
46485     };
46486
46487     // 'stamp' an authentication object from `getAuth()`
46488     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
46489     // and timestamp
46490     function timenonce(o) {
46491         o.oauth_timestamp = ohauth.timestamp();
46492         o.oauth_nonce = ohauth.nonce();
46493         return o;
46494     }
46495
46496     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46497     // can be used with multiple APIs and the keys in `localStorage`
46498     // will not clash
46499     var token;
46500
46501     if (store.enabled) {
46502         token = function (x, y) {
46503             if (arguments.length === 1) return store.get(o.url + x);
46504             else if (arguments.length === 2) return store.set(o.url + x, y);
46505         };
46506     } else {
46507         var storage = {};
46508         token = function (x, y) {
46509             if (arguments.length === 1) return storage[o.url + x];
46510             else if (arguments.length === 2) return storage[o.url + x] = y;
46511         };
46512     }
46513
46514     // Get an authentication object. If you just add and remove properties
46515     // from a single object, you'll need to use `delete` to make sure that
46516     // it doesn't contain undesired properties for authentication
46517     function getAuth(o) {
46518         return {
46519             oauth_consumer_key: o.oauth_consumer_key,
46520             oauth_signature_method: 'HMAC-SHA1'
46521         };
46522     }
46523
46524     // potentially pre-authorize
46525     oauth.options(o);
46526
46527     return oauth;
46528 };
46529
46530 var JXON = new (function () {
46531   var
46532     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46533     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46534
46535   function parseText (sValue) {
46536     if (rIsNull.test(sValue)) { return null; }
46537     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46538     if (isFinite(sValue)) { return parseFloat(sValue); }
46539     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46540     return sValue;
46541   }
46542
46543   function EmptyTree () { }
46544   EmptyTree.prototype.toString = function () { return 'null'; };
46545   EmptyTree.prototype.valueOf = function () { return null; };
46546
46547   function objectify (vValue) {
46548     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46549   }
46550
46551   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46552     var
46553       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46554       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46555
46556     var
46557       sProp, vContent, nLength = 0, sCollectedTxt = '',
46558       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46559
46560     if (bChildren) {
46561       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46562         oNode = oParentNode.childNodes.item(nItem);
46563         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46564         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46565         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46566       }
46567     }
46568
46569     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46570
46571     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46572
46573     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46574       sProp = aCache[nElId].nodeName.toLowerCase();
46575       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46576       if (vResult.hasOwnProperty(sProp)) {
46577         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46578         vResult[sProp].push(vContent);
46579       } else {
46580         vResult[sProp] = vContent;
46581         nLength++;
46582       }
46583     }
46584
46585     if (bAttributes) {
46586       var
46587         nAttrLen = oParentNode.attributes.length,
46588         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46589
46590       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46591         oAttrib = oParentNode.attributes.item(nAttrib);
46592         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46593       }
46594
46595       if (bNesteAttr) {
46596         if (bFreeze) { Object.freeze(oAttrParent); }
46597         vResult[sAttributesProp] = oAttrParent;
46598         nLength -= nAttrLen - 1;
46599       }
46600     }
46601
46602     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46603       vResult[sValueProp] = vBuiltVal;
46604     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46605       vResult = vBuiltVal;
46606     }
46607
46608     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46609
46610     aCache.length = nLevelStart;
46611
46612     return vResult;
46613   }
46614
46615   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46616     var vValue, oChild;
46617
46618     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46619       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46620     } else if (oParentObj.constructor === Date) {
46621       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46622     }
46623
46624     for (var sName in oParentObj) {
46625       vValue = oParentObj[sName];
46626       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46627       if (sName === sValueProp) {
46628         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46629       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46630         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46631       } else if (sName.charAt(0) === sAttrPref) {
46632         oParentEl.setAttribute(sName.slice(1), vValue);
46633       } else if (vValue.constructor === Array) {
46634         for (var nItem = 0; nItem < vValue.length; nItem++) {
46635           oChild = oXMLDoc.createElement(sName);
46636           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46637           oParentEl.appendChild(oChild);
46638         }
46639       } else {
46640         oChild = oXMLDoc.createElement(sName);
46641         if (vValue instanceof Object) {
46642           loadObjTree(oXMLDoc, oChild, vValue);
46643         } else if (vValue !== null && vValue !== true) {
46644           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46645         }
46646         oParentEl.appendChild(oChild);
46647      }
46648    }
46649   }
46650
46651   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46652     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46653     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46654   };
46655
46656   this.unbuild = function (oObjTree) {    
46657     var oNewDoc = document.implementation.createDocument('', '', null);
46658     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46659     return oNewDoc;
46660   };
46661
46662   this.stringify = function (oObjTree) {
46663     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46664   };
46665 })();
46666
46667 // var myObject = JXON.build(doc);
46668 // we got our javascript object! try: alert(JSON.stringify(myObject));
46669
46670 // var newDoc = JXON.unbuild(myObject);
46671 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46672
46673 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46674 var useHttps = window.location.protocol === 'https:';
46675 var protocol = useHttps ? 'https:' : 'http:';
46676 var urlroot = protocol + '//www.openstreetmap.org';
46677 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46678 var inflight = {};
46679 var loadedTiles = {};
46680 var tileZoom$1 = 16;
46681 var oauth = index$12({
46682         url: urlroot,
46683         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46684         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46685         loading: authLoading,
46686         done: authDone
46687     });
46688 var rateLimitError;
46689 var userChangesets;
46690 var userDetails;
46691 var off;
46692
46693
46694 function authLoading() {
46695     dispatch$3.call('authLoading');
46696 }
46697
46698
46699 function authDone() {
46700     dispatch$3.call('authDone');
46701 }
46702
46703
46704 function abortRequest$1(i) {
46705     if (i) {
46706         i.abort();
46707     }
46708 }
46709
46710
46711 function getLoc(attrs) {
46712     var lon = attrs.lon && attrs.lon.value,
46713         lat = attrs.lat && attrs.lat.value;
46714     return [parseFloat(lon), parseFloat(lat)];
46715 }
46716
46717
46718 function getNodes(obj) {
46719     var elems = obj.getElementsByTagName('nd'),
46720         nodes = new Array(elems.length);
46721     for (var i = 0, l = elems.length; i < l; i++) {
46722         nodes[i] = 'n' + elems[i].attributes.ref.value;
46723     }
46724     return nodes;
46725 }
46726
46727
46728 function getTags(obj) {
46729     var elems = obj.getElementsByTagName('tag'),
46730         tags = {};
46731     for (var i = 0, l = elems.length; i < l; i++) {
46732         var attrs = elems[i].attributes;
46733         tags[attrs.k.value] = attrs.v.value;
46734     }
46735
46736     return tags;
46737 }
46738
46739
46740 function getMembers(obj) {
46741     var elems = obj.getElementsByTagName('member'),
46742         members = new Array(elems.length);
46743     for (var i = 0, l = elems.length; i < l; i++) {
46744         var attrs = elems[i].attributes;
46745         members[i] = {
46746             id: attrs.type.value[0] + attrs.ref.value,
46747             type: attrs.type.value,
46748             role: attrs.role.value
46749         };
46750     }
46751     return members;
46752 }
46753
46754
46755 function getVisible(attrs) {
46756     return (!attrs.visible || attrs.visible.value !== 'false');
46757 }
46758
46759
46760 var parsers = {
46761     node: function nodeData(obj) {
46762         var attrs = obj.attributes;
46763         return new osmNode({
46764             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46765             loc: getLoc(attrs),
46766             version: attrs.version.value,
46767             user: attrs.user && attrs.user.value,
46768             tags: getTags(obj),
46769             visible: getVisible(attrs)
46770         });
46771     },
46772
46773     way: function wayData(obj) {
46774         var attrs = obj.attributes;
46775         return new osmWay({
46776             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46777             version: attrs.version.value,
46778             user: attrs.user && attrs.user.value,
46779             tags: getTags(obj),
46780             nodes: getNodes(obj),
46781             visible: getVisible(attrs)
46782         });
46783     },
46784
46785     relation: function relationData(obj) {
46786         var attrs = obj.attributes;
46787         return new osmRelation({
46788             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46789             version: attrs.version.value,
46790             user: attrs.user && attrs.user.value,
46791             tags: getTags(obj),
46792             members: getMembers(obj),
46793             visible: getVisible(attrs)
46794         });
46795     }
46796 };
46797
46798
46799 function parse(xml$$1) {
46800     if (!xml$$1 || !xml$$1.childNodes) return;
46801
46802     var root = xml$$1.childNodes[0],
46803         children = root.childNodes,
46804         entities = [];
46805
46806     for (var i = 0, l = children.length; i < l; i++) {
46807         var child = children[i],
46808             parser = parsers[child.nodeName];
46809         if (parser) {
46810             entities.push(parser(child));
46811         }
46812     }
46813
46814     return entities;
46815 }
46816
46817
46818 var serviceOsm = {
46819
46820     init: function() {
46821         utilRebind(this, dispatch$3, 'on');
46822     },
46823
46824
46825     reset: function() {
46826         userChangesets = undefined;
46827         userDetails = undefined;
46828         rateLimitError = undefined;
46829         lodash.forEach(inflight, abortRequest$1);
46830         loadedTiles = {};
46831         inflight = {};
46832         return this;
46833     },
46834
46835
46836     changesetURL: function(changesetId) {
46837         return urlroot + '/changeset/' + changesetId;
46838     },
46839
46840
46841     changesetsURL: function(center, zoom$$1) {
46842         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46843         return urlroot + '/history#map=' +
46844             Math.floor(zoom$$1) + '/' +
46845             center[1].toFixed(precision) + '/' +
46846             center[0].toFixed(precision);
46847     },
46848
46849
46850     entityURL: function(entity) {
46851         return urlroot + '/' + entity.type + '/' + entity.osmId();
46852     },
46853
46854
46855     userURL: function(username) {
46856         return urlroot + '/user/' + username;
46857     },
46858
46859
46860     loadFromAPI: function(path$$1, callback) {
46861         var that = this;
46862
46863         function done(err, xml$$1) {
46864             var isAuthenticated = that.authenticated();
46865
46866             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46867             // Logout and retry the request..
46868             if (isAuthenticated && err &&
46869                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46870                 that.logout();
46871                 that.loadFromAPI(path$$1, callback);
46872
46873             // else, no retry..
46874             } else {
46875                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46876                 // Set the rateLimitError flag and trigger a warning..
46877                 if (!isAuthenticated && !rateLimitError && err &&
46878                         (err.status === 509 || err.status === 429)) {
46879                     rateLimitError = err;
46880                     dispatch$3.call('change');
46881                 }
46882
46883                 if (callback) {
46884                     callback(err, parse(xml$$1));
46885                 }
46886             }
46887         }
46888
46889         if (this.authenticated()) {
46890             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46891         } else {
46892             var url = urlroot + path$$1;
46893             return xml(url).get(done);
46894         }
46895     },
46896
46897
46898     loadEntity: function(id, callback) {
46899         var type = osmEntity$$1.id.type(id),
46900             osmID = osmEntity$$1.id.toOSM(id);
46901
46902         this.loadFromAPI(
46903             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46904             function(err, entities) {
46905                 if (callback) callback(err, { data: entities });
46906             }
46907         );
46908     },
46909
46910
46911     loadEntityVersion: function(id, version$$1, callback) {
46912         var type = osmEntity$$1.id.type(id),
46913             osmID = osmEntity$$1.id.toOSM(id);
46914
46915         this.loadFromAPI(
46916             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46917             function(err, entities) {
46918                 if (callback) callback(err, { data: entities });
46919             }
46920         );
46921     },
46922
46923
46924     loadMultiple: function(ids, callback) {
46925         var that = this;
46926         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46927             var type = k + 's',
46928                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46929
46930             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46931                 that.loadFromAPI(
46932                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46933                     function(err, entities) {
46934                         if (callback) callback(err, { data: entities });
46935                     }
46936                 );
46937             });
46938         });
46939     },
46940
46941
46942     authenticated: function() {
46943         return oauth.authenticated();
46944     },
46945
46946
46947     // Generate Changeset XML. Returns a string.
46948     changesetJXON: function(tags) {
46949         return {
46950             osm: {
46951                 changeset: {
46952                     tag: lodash.map(tags, function(value, key) {
46953                         return { '@k': key, '@v': value };
46954                     }),
46955                     '@version': 0.6,
46956                     '@generator': 'iD'
46957                 }
46958             }
46959         };
46960     },
46961
46962
46963     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46964     // XML. Returns a string.
46965     osmChangeJXON: function(changeset_id, changes) {
46966         function nest$$1(x, order) {
46967             var groups = {};
46968             for (var i = 0; i < x.length; i++) {
46969                 var tagName = Object.keys(x[i])[0];
46970                 if (!groups[tagName]) groups[tagName] = [];
46971                 groups[tagName].push(x[i][tagName]);
46972             }
46973             var ordered = {};
46974             order.forEach(function(o) {
46975                 if (groups[o]) ordered[o] = groups[o];
46976             });
46977             return ordered;
46978         }
46979
46980         function rep(entity) {
46981             return entity.asJXON(changeset_id);
46982         }
46983
46984         return {
46985             osmChange: {
46986                 '@version': 0.6,
46987                 '@generator': 'iD',
46988                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
46989                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
46990                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
46991             }
46992         };
46993     },
46994
46995
46996     changesetTags: function(version$$1, comment, imageryUsed) {
46997         var detected = utilDetect(),
46998             tags = {
46999                 created_by: ('iD ' + version$$1).substr(0, 255),
47000                 imagery_used: imageryUsed.join(';').substr(0, 255),
47001                 host: detected.host.substr(0, 255),
47002                 locale: detected.locale.substr(0, 255)
47003             };
47004
47005         if (comment) {
47006             tags.comment = comment.substr(0, 255);
47007         }
47008
47009         return tags;
47010     },
47011
47012
47013     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
47014         var that = this;
47015         oauth.xhr({
47016                 method: 'PUT',
47017                 path: '/api/0.6/changeset/create',
47018                 options: { header: { 'Content-Type': 'text/xml' } },
47019                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
47020             }, function(err, changeset_id) {
47021                 if (err) return callback(err);
47022                 oauth.xhr({
47023                     method: 'POST',
47024                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
47025                     options: { header: { 'Content-Type': 'text/xml' } },
47026                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
47027                 }, function(err) {
47028                     if (err) return callback(err);
47029                     // POST was successful, safe to call the callback.
47030                     // Still attempt to close changeset, but ignore response because #2667
47031                     // Add delay to allow for postgres replication #1646 #2678
47032                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
47033                     oauth.xhr({
47034                         method: 'PUT',
47035                         path: '/api/0.6/changeset/' + changeset_id + '/close',
47036                         options: { header: { 'Content-Type': 'text/xml' } }
47037                     }, function() { return true; });
47038                 });
47039             });
47040     },
47041
47042
47043     userDetails: function(callback) {
47044         if (userDetails) {
47045             callback(undefined, userDetails);
47046             return;
47047         }
47048
47049         function done(err, user_details) {
47050             if (err) return callback(err);
47051
47052             var u = user_details.getElementsByTagName('user')[0],
47053                 img = u.getElementsByTagName('img'),
47054                 image_url = '';
47055
47056             if (img && img[0] && img[0].getAttribute('href')) {
47057                 image_url = img[0].getAttribute('href');
47058             }
47059
47060             userDetails = {
47061                 display_name: u.attributes.display_name.value,
47062                 image_url: image_url,
47063                 id: u.attributes.id.value
47064             };
47065
47066             callback(undefined, userDetails);
47067         }
47068
47069         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
47070     },
47071
47072
47073     userChangesets: function(callback) {
47074         if (userChangesets) {
47075             callback(undefined, userChangesets);
47076             return;
47077         }
47078
47079         this.userDetails(function(err, user) {
47080             if (err) {
47081                 callback(err);
47082                 return;
47083             }
47084
47085             function done(err, changesets) {
47086                 if (err) {
47087                     callback(err);
47088                 } else {
47089                     userChangesets = Array.prototype.map.call(
47090                         changesets.getElementsByTagName('changeset'),
47091                         function (changeset) {
47092                             return { tags: getTags(changeset) };
47093                         }
47094                     );
47095                     callback(undefined, userChangesets);
47096                 }
47097             }
47098
47099             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
47100         });
47101     },
47102
47103
47104     status: function(callback) {
47105         function done(xml$$1) {
47106             // update blacklists
47107             var elements = xml$$1.getElementsByTagName('blacklist'),
47108                 regexes = [];
47109             for (var i = 0; i < elements.length; i++) {
47110                 var regex = elements[i].getAttribute('regex');  // needs unencode?
47111                 if (regex) {
47112                     regexes.push(regex);
47113                 }
47114             }
47115             if (regexes.length) {
47116                 blacklists = regexes;
47117             }
47118
47119
47120             if (rateLimitError) {
47121                 callback(rateLimitError, 'rateLimited');
47122             } else {
47123                 var apiStatus = xml$$1.getElementsByTagName('status'),
47124                     val = apiStatus[0].getAttribute('api');
47125
47126                 callback(undefined, val);
47127             }
47128         }
47129
47130         xml(urlroot + '/api/capabilities').get()
47131             .on('load', done)
47132             .on('error', callback);
47133     },
47134
47135
47136     imageryBlacklists: function() {
47137         return blacklists;
47138     },
47139
47140
47141     tileZoom: function(_) {
47142         if (!arguments.length) return tileZoom$1;
47143         tileZoom$1 = _;
47144         return this;
47145     },
47146
47147
47148     loadTiles: function(projection, dimensions, callback) {
47149         if (off) return;
47150
47151         var that = this,
47152             s = projection.scale() * 2 * Math.PI,
47153             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
47154             ts = 256 * Math.pow(2, z - tileZoom$1),
47155             origin = [
47156                 s / 2 - projection.translate()[0],
47157                 s / 2 - projection.translate()[1]
47158             ];
47159
47160         var tiles = d3geoTile()
47161             .scaleExtent([tileZoom$1, tileZoom$1])
47162             .scale(s)
47163             .size(dimensions)
47164             .translate(projection.translate())()
47165             .map(function(tile) {
47166                 var x = tile[0] * ts - origin[0],
47167                     y = tile[1] * ts - origin[1];
47168
47169                 return {
47170                     id: tile.toString(),
47171                     extent: geoExtent$$1(
47172                         projection.invert([x, y + ts]),
47173                         projection.invert([x + ts, y]))
47174                 };
47175             });
47176
47177         lodash.filter(inflight, function(v, i) {
47178             var wanted = lodash.find(tiles, function(tile) {
47179                 return i === tile.id;
47180             });
47181             if (!wanted) delete inflight[i];
47182             return !wanted;
47183         }).map(abortRequest$1);
47184
47185         tiles.forEach(function(tile) {
47186             var id = tile.id;
47187
47188             if (loadedTiles[id] || inflight[id]) return;
47189
47190             if (lodash.isEmpty(inflight)) {
47191                 dispatch$3.call('loading');
47192             }
47193
47194             inflight[id] = that.loadFromAPI(
47195                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
47196                 function(err, parsed) {
47197                     delete inflight[id];
47198                     if (!err) {
47199                         loadedTiles[id] = true;
47200                     }
47201
47202                     if (callback) {
47203                         callback(err, lodash.extend({ data: parsed }, tile));
47204                     }
47205
47206                     if (lodash.isEmpty(inflight)) {
47207                         dispatch$3.call('loaded');
47208                     }
47209                 }
47210             );
47211         });
47212     },
47213
47214
47215     switch: function(options) {
47216         urlroot = options.urlroot;
47217
47218         oauth.options(lodash.extend({
47219             url: urlroot,
47220             loading: authLoading,
47221             done: authDone
47222         }, options));
47223
47224         dispatch$3.call('change');
47225         this.reset();
47226         this.userChangesets(function() {});  // eagerly load user details/changesets
47227         return this;
47228     },
47229
47230
47231     toggle: function(_) {
47232         off = !_;
47233         return this;
47234     },
47235
47236
47237     loadedTiles: function(_) {
47238         if (!arguments.length) return loadedTiles;
47239         loadedTiles = _;
47240         return this;
47241     },
47242
47243
47244     logout: function() {
47245         userChangesets = undefined;
47246         userDetails = undefined;
47247         oauth.logout();
47248         dispatch$3.call('change');
47249         return this;
47250     },
47251
47252
47253     authenticate: function(callback) {
47254         var that = this;
47255         userChangesets = undefined;
47256         userDetails = undefined;
47257
47258         function done(err, res) {
47259             rateLimitError = undefined;
47260             dispatch$3.call('change');
47261             if (callback) callback(err, res);
47262             that.userChangesets(function() {});  // eagerly load user details/changesets
47263         }
47264
47265         return oauth.authenticate(done);
47266     }
47267 };
47268
47269 var endpoint = 'https://taginfo.openstreetmap.org/api/4/';
47270 var taginfoCache = {};
47271 var tag_sorts = {
47272         point: 'count_nodes',
47273         vertex: 'count_nodes',
47274         area: 'count_ways',
47275         line: 'count_ways'
47276     };
47277 var tag_sort_members = {
47278         point: 'count_node_members',
47279         vertex: 'count_node_members',
47280         area: 'count_way_members',
47281         line: 'count_way_members',
47282         relation: 'count_relation_members'
47283     };
47284 var tag_filters = {
47285         point: 'nodes',
47286         vertex: 'nodes',
47287         area: 'ways',
47288         line: 'ways'
47289     };
47290 var tag_members_fractions = {
47291         point: 'count_node_members_fraction',
47292         vertex: 'count_node_members_fraction',
47293         area: 'count_way_members_fraction',
47294         line: 'count_way_members_fraction',
47295         relation: 'count_relation_members_fraction'
47296     };
47297
47298
47299 function sets(parameters, n, o) {
47300     if (parameters.geometry && o[parameters.geometry]) {
47301         parameters[n] = o[parameters.geometry];
47302     }
47303     return parameters;
47304 }
47305
47306
47307 function setFilter(parameters) {
47308     return sets(parameters, 'filter', tag_filters);
47309 }
47310
47311
47312 function setSort(parameters) {
47313     return sets(parameters, 'sortname', tag_sorts);
47314 }
47315
47316
47317 function setSortMembers(parameters) {
47318     return sets(parameters, 'sortname', tag_sort_members);
47319 }
47320
47321
47322 function clean(parameters) {
47323     return lodash.omit(parameters, 'geometry', 'debounce');
47324 }
47325
47326
47327 function filterKeys(type) {
47328     var count_type = type ? 'count_' + type : 'count_all';
47329     return function(d) {
47330         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
47331     };
47332 }
47333
47334
47335 function filterMultikeys(prefix) {
47336     return function(d) {
47337         // d.key begins with prefix, and d.key contains no additional ':'s
47338         var re = new RegExp('^' + prefix + '(.*)$');
47339         var matches = d.key.match(re) || [];
47340         return (matches.length === 2 && matches[1].indexOf(':') === -1);
47341     };
47342 }
47343
47344
47345 function filterValues(allowUpperCase) {
47346     return function(d) {
47347         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
47348         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
47349         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
47350     };
47351 }
47352
47353
47354 function filterRoles(geometry) {
47355     return function(d) {
47356         if (d.role === '') return false; // exclude empty role
47357         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
47358         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
47359     };
47360 }
47361
47362
47363 function valKey(d) {
47364     return {
47365         value: d.key,
47366         title: d.key
47367     };
47368 }
47369
47370
47371 function valKeyDescription(d) {
47372     return {
47373         value: d.value,
47374         title: d.description || d.value
47375     };
47376 }
47377
47378
47379 function roleKey(d) {
47380     return {
47381         value: d.role,
47382         title: d.role
47383     };
47384 }
47385
47386
47387 // sort keys with ':' lower than keys without ':'
47388 function sortKeys(a, b) {
47389     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
47390         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
47391         : 0;
47392 }
47393
47394
47395 var debounced = lodash.debounce(json, 100, true);
47396
47397
47398 function request$1(url, debounce, callback) {
47399     if (taginfoCache[url]) {
47400         callback(null, taginfoCache[url]);
47401     } else if (debounce) {
47402         debounced(url, done);
47403     } else {
47404         json(url, done);
47405     }
47406
47407     function done(err, data) {
47408         if (!err) {
47409             taginfoCache[url] = data;
47410         }
47411         callback(err, data);
47412     }
47413 }
47414
47415
47416 var serviceTaginfo = {
47417
47418     init: function() { taginfoCache = {}; },
47419     reset: function() { taginfoCache = {}; },
47420
47421
47422     keys: function(parameters, callback) {
47423         var debounce = parameters.debounce;
47424         parameters = clean(setSort(parameters));
47425         request$1(endpoint + 'keys/all?' +
47426             utilQsString(lodash.extend({
47427                 rp: 10,
47428                 sortname: 'count_all',
47429                 sortorder: 'desc',
47430                 page: 1
47431             }, parameters)), debounce, function(err, d) {
47432                 if (err) {
47433                     callback(err);
47434                 } else {
47435                     var f = filterKeys(parameters.filter);
47436                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
47437                 }
47438             }
47439         );
47440     },
47441
47442
47443     multikeys: function(parameters, callback) {
47444         var debounce = parameters.debounce;
47445         parameters = clean(setSort(parameters));
47446         var prefix = parameters.query;
47447         request$1(endpoint + 'keys/all?' +
47448             utilQsString(lodash.extend({
47449                 rp: 25,
47450                 sortname: 'count_all',
47451                 sortorder: 'desc',
47452                 page: 1
47453             }, parameters)), debounce, function(err, d) {
47454                 if (err) {
47455                     callback(err);
47456                 } else {
47457                     var f = filterMultikeys(prefix);
47458                     callback(null, d.data.filter(f).map(valKey));
47459                 }
47460             }
47461         );
47462     },
47463
47464
47465     values: function(parameters, callback) {
47466         var debounce = parameters.debounce;
47467         parameters = clean(setSort(setFilter(parameters)));
47468         request$1(endpoint + 'key/values?' +
47469             utilQsString(lodash.extend({
47470                 rp: 25,
47471                 sortname: 'count_all',
47472                 sortorder: 'desc',
47473                 page: 1
47474             }, parameters)), debounce, function(err, d) {
47475                 if (err) {
47476                     callback(err);
47477                 } else {
47478                     // In most cases we prefer taginfo value results with lowercase letters.
47479                     // A few OSM keys expect values to contain uppercase values (see #3377).
47480                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
47481                     // but these are the fields where taginfo value lookup is most useful.
47482                     var re = /network|taxon|genus|species/;
47483                     var allowUpperCase = (parameters.key.match(re) !== null);
47484                     var f = filterValues(allowUpperCase);
47485                     callback(null, d.data.filter(f).map(valKeyDescription));
47486                 }
47487             }
47488         );
47489     },
47490
47491
47492     roles: function(parameters, callback) {
47493         var debounce = parameters.debounce;
47494         var geometry = parameters.geometry;
47495         parameters = clean(setSortMembers(parameters));
47496         request$1(endpoint + 'relation/roles?' +
47497             utilQsString(lodash.extend({
47498                 rp: 25,
47499                 sortname: 'count_all_members',
47500                 sortorder: 'desc',
47501                 page: 1
47502             }, parameters)), debounce, function(err, d) {
47503                 if (err) {
47504                     callback(err);
47505                 } else {
47506                     var f = filterRoles(geometry);
47507                     callback(null, d.data.filter(f).map(roleKey));
47508                 }
47509             }
47510         );
47511     },
47512
47513
47514     docs: function(parameters, callback) {
47515         var debounce = parameters.debounce;
47516         parameters = clean(setSort(parameters));
47517
47518         var path$$1 = 'key/wiki_pages?';
47519         if (parameters.value) path$$1 = 'tag/wiki_pages?';
47520         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
47521
47522         request$1(endpoint + path$$1 + utilQsString(parameters), debounce, function(err, d) {
47523             if (err) {
47524                 callback(err);
47525             } else {
47526                 callback(null, d.data);
47527             }
47528         });
47529     },
47530
47531
47532     endpoint: function(_) {
47533         if (!arguments.length) return endpoint;
47534         endpoint = _;
47535         return this;
47536     }
47537
47538 };
47539
47540 var jsonpCache = {};
47541 window.jsonpCache = jsonpCache;
47542
47543 function jsonpRequest(url, callback) {
47544
47545   if (window.JSONP_FIX) {
47546     if (window.JSONP_DELAY === 0) {
47547       callback(window.JSONP_FIX);
47548     } else {
47549       setTimeout(function() {
47550         callback(window.JSONP_FIX);
47551       }, window.JSONP_DELAY || 0);
47552     }
47553     return;
47554   }
47555
47556   function rand() {
47557     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47558       c = '', i = -1;
47559     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47560     return c;
47561   }
47562
47563   function create(url) {
47564     var e = url.match(/callback=(\w+)/),
47565       c = e ? e[1] : rand();
47566     jsonpCache[c] = function(data) {
47567       callback(data);
47568       delete jsonpCache[c];
47569       script.remove();
47570     };
47571     return 'jsonpCache.' + c;
47572   }
47573
47574   var cb = create(url),
47575     script = select('head')
47576     .append('script')
47577     .attr('type', 'text/javascript')
47578     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47579 }
47580
47581 var endpoint$1 = 'https://www.wikidata.org/w/api.php?';
47582
47583 var serviceWikidata = {
47584
47585     init: function() {},
47586     reset: function() {},
47587
47588
47589     // Given a Wikipedia language and article title, return an array of
47590     // corresponding Wikidata entities.
47591     itemsByTitle: function(lang, title, callback) {
47592         if (!title) {
47593             callback('', {});
47594             return;
47595         }
47596
47597         lang = lang || 'en';
47598         jsonpRequest(endpoint$1 + utilQsString({
47599             action: 'wbgetentities',
47600             format: 'json',
47601             sites: lang.replace(/-/g, '_') + 'wiki',
47602             titles: title,
47603             languages: 'en', // shrink response by filtering to one language
47604             callback: '{callback}'
47605         }), function(data) {
47606             if (!data || data.error) {
47607                 callback('', {});
47608             } else {
47609                 callback(title, data.entities || {});
47610             }
47611         });
47612     }
47613
47614 };
47615
47616 var endpoint$2 = 'https://en.wikipedia.org/w/api.php?';
47617
47618 var serviceWikipedia = {
47619
47620     init: function() {},
47621     reset: function() {},
47622
47623
47624     search: function(lang, query, callback) {
47625         if (!query) {
47626             callback('', []);
47627             return;
47628         }
47629
47630         lang = lang || 'en';
47631         jsonpRequest(endpoint$2.replace('en', lang) +
47632             utilQsString({
47633                 action: 'query',
47634                 list: 'search',
47635                 srlimit: '10',
47636                 srinfo: 'suggestion',
47637                 format: 'json',
47638                 callback: '{callback}',
47639                 srsearch: query
47640             }), function(data) {
47641                 if (!data || !data.query || !data.query.search || data.error) {
47642                     callback('', []);
47643                 } else {
47644                     var results = data.query.search.map(function(d) { return d.title; });
47645                     callback(query, results);
47646                 }
47647             }
47648         );
47649     },
47650
47651
47652     suggestions: function(lang, query, callback) {
47653         if (!query) {
47654             callback('', []);
47655             return;
47656         }
47657
47658         lang = lang || 'en';
47659         jsonpRequest(endpoint$2.replace('en', lang) +
47660             utilQsString({
47661                 action: 'opensearch',
47662                 namespace: 0,
47663                 suggest: '',
47664                 format: 'json',
47665                 callback: '{callback}',
47666                 search: query
47667             }), function(data) {
47668                 if (!data || data.error) {
47669                     callback('', []);
47670                 } else {
47671                     callback(data[0], data[1] || []);
47672                 }
47673             }
47674         );
47675     },
47676
47677
47678     translations: function(lang, title, callback) {
47679         if (!title) {
47680             callback({});
47681             return;
47682         }
47683
47684         jsonpRequest(endpoint$2.replace('en', lang) +
47685             utilQsString({
47686                 action: 'query',
47687                 prop: 'langlinks',
47688                 format: 'json',
47689                 callback: '{callback}',
47690                 lllimit: 500,
47691                 titles: title
47692             }), function(data) {
47693                 if (!data || !data.query || !data.query.pages || data.error) {
47694                     callback({});
47695                 } else {
47696                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47697                         translations = {};
47698                     if (list && list.langlinks) {
47699                         list.langlinks.forEach(function(d) {
47700                             translations[d.lang] = d['*'];
47701                         });
47702                     }
47703                     callback(translations);
47704                 }
47705             }
47706         );
47707     }
47708
47709 };
47710
47711 var services = {
47712     mapillary: serviceMapillary,
47713     geocoder: serviceNominatim,
47714     osm: serviceOsm,
47715     taginfo: serviceTaginfo,
47716     wikidata: serviceWikidata,
47717     wikipedia: serviceWikipedia
47718 };
47719
47720 function svgMapillaryImages(projection, context, dispatch$$1) {
47721     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47722         minZoom = 12,
47723         minViewfieldZoom = 17,
47724         layer = select(null),
47725         _mapillary;
47726
47727
47728     function init() {
47729         if (svgMapillaryImages.initialized) return;  // run once
47730         svgMapillaryImages.enabled = false;
47731         svgMapillaryImages.initialized = true;
47732     }
47733
47734
47735     function getMapillary() {
47736         if (services.mapillary && !_mapillary) {
47737             _mapillary = services.mapillary;
47738             _mapillary.event.on('loadedImages', throttledRedraw);
47739         } else if (!services.mapillary && _mapillary) {
47740             _mapillary = null;
47741         }
47742
47743         return _mapillary;
47744     }
47745
47746
47747     function showLayer() {
47748         var mapillary = getMapillary();
47749         if (!mapillary) return;
47750
47751         mapillary.loadViewer(context);
47752         editOn();
47753
47754         layer
47755             .style('opacity', 0)
47756             .transition()
47757             .duration(500)
47758             .style('opacity', 1)
47759             .on('end', function () { dispatch$$1.call('change'); });
47760     }
47761
47762
47763     function hideLayer() {
47764         var mapillary = getMapillary();
47765         if (mapillary) {
47766             mapillary.hideViewer();
47767         }
47768
47769         throttledRedraw.cancel();
47770
47771         layer
47772             .transition()
47773             .duration(500)
47774             .style('opacity', 0)
47775             .on('end', editOff);
47776     }
47777
47778
47779     function editOn() {
47780         layer.style('display', 'block');
47781     }
47782
47783
47784     function editOff() {
47785         layer.selectAll('.viewfield-group').remove();
47786         layer.style('display', 'none');
47787     }
47788
47789
47790     function click(d) {
47791         var mapillary = getMapillary();
47792         if (!mapillary) return;
47793
47794         context.map().centerEase(d.loc);
47795
47796         mapillary
47797             .selectedImage(d.key, true)
47798             .updateViewer(d.key, context)
47799             .showViewer();
47800     }
47801
47802
47803     function transform(d) {
47804         var t = svgPointTransform(projection)(d);
47805         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47806         return t;
47807     }
47808
47809
47810     function update() {
47811         var mapillary = getMapillary(),
47812             data = (mapillary ? mapillary.images(projection) : []),
47813             imageKey = mapillary ? mapillary.selectedImage() : null;
47814
47815         var markers = layer.selectAll('.viewfield-group')
47816             .data(data, function(d) { return d.key; });
47817
47818         markers.exit()
47819             .remove();
47820
47821         var enter = markers.enter()
47822             .append('g')
47823             .attr('class', 'viewfield-group')
47824             .classed('selected', function(d) { return d.key === imageKey; })
47825             .on('click', click);
47826
47827         markers = markers
47828             .merge(enter)
47829             .attr('transform', transform);
47830
47831
47832        var viewfields = markers.selectAll('.viewfield')
47833             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47834
47835         viewfields.exit()
47836             .remove();
47837
47838         viewfields.enter()
47839             .append('path')
47840             .attr('class', 'viewfield')
47841             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47842             .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');
47843
47844         markers.selectAll('circle')
47845             .data([0])
47846             .enter()
47847             .append('circle')
47848             .attr('dx', '0')
47849             .attr('dy', '0')
47850             .attr('r', '6');
47851     }
47852
47853
47854     function drawImages(selection$$1) {
47855         var enabled = svgMapillaryImages.enabled,
47856             mapillary = getMapillary();
47857
47858         layer = selection$$1.selectAll('.layer-mapillary-images')
47859             .data(mapillary ? [0] : []);
47860
47861         layer.exit()
47862             .remove();
47863
47864         layer = layer.enter()
47865             .append('g')
47866             .attr('class', 'layer-mapillary-images')
47867             .style('display', enabled ? 'block' : 'none')
47868             .merge(layer);
47869
47870         if (enabled) {
47871             if (mapillary && ~~context.map().zoom() >= minZoom) {
47872                 editOn();
47873                 update();
47874                 mapillary.loadImages(projection);
47875             } else {
47876                 editOff();
47877             }
47878         }
47879     }
47880
47881
47882     drawImages.enabled = function(_) {
47883         if (!arguments.length) return svgMapillaryImages.enabled;
47884         svgMapillaryImages.enabled = _;
47885         if (svgMapillaryImages.enabled) {
47886             showLayer();
47887         } else {
47888             hideLayer();
47889         }
47890         dispatch$$1.call('change');
47891         return this;
47892     };
47893
47894
47895     drawImages.supported = function() {
47896         return !!getMapillary();
47897     };
47898
47899
47900     init();
47901     return drawImages;
47902 }
47903
47904 function svgMapillarySigns(projection, context, dispatch$$1) {
47905     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47906         minZoom = 12,
47907         layer = select(null),
47908         _mapillary;
47909
47910
47911     function init() {
47912         if (svgMapillarySigns.initialized) return;  // run once
47913         svgMapillarySigns.enabled = false;
47914         svgMapillarySigns.initialized = true;
47915     }
47916
47917
47918     function getMapillary() {
47919         if (services.mapillary && !_mapillary) {
47920             _mapillary = services.mapillary;
47921             _mapillary.event.on('loadedSigns', throttledRedraw);
47922         } else if (!services.mapillary && _mapillary) {
47923             _mapillary = null;
47924         }
47925         return _mapillary;
47926     }
47927
47928
47929     function showLayer() {
47930         editOn();
47931     }
47932
47933
47934     function hideLayer() {
47935         throttledRedraw.cancel();
47936         editOff();
47937     }
47938
47939
47940     function editOn() {
47941         layer.style('display', 'block');
47942     }
47943
47944
47945     function editOff() {
47946         layer.selectAll('.icon-sign').remove();
47947         layer.style('display', 'none');
47948     }
47949
47950
47951     function click(d) {
47952         var mapillary = getMapillary();
47953         if (!mapillary) return;
47954
47955         context.map().centerEase(d.loc);
47956
47957         mapillary
47958             .selectedImage(d.key, true)
47959             .updateViewer(d.key, context)
47960             .showViewer();
47961     }
47962
47963
47964     function update() {
47965         var mapillary = getMapillary(),
47966             data = (mapillary ? mapillary.signs(projection) : []),
47967             imageKey = mapillary ? mapillary.selectedImage() : null;
47968
47969         var signs = layer.selectAll('.icon-sign')
47970             .data(data, function(d) { return d.key; });
47971
47972         signs.exit()
47973             .remove();
47974
47975         var enter = signs.enter()
47976             .append('foreignObject')
47977             .attr('class', 'icon-sign')
47978             .attr('width', '32px')      // for Firefox
47979             .attr('height', '32px')     // for Firefox
47980             .classed('selected', function(d) { return d.key === imageKey; })
47981             .on('click', click);
47982
47983         enter
47984             .append('xhtml:body')
47985             .attr('class', 'icon-sign-body')
47986             .html(mapillary.signHTML);
47987
47988         signs
47989             .merge(enter)
47990             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
47991             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
47992     }
47993
47994
47995     function drawSigns(selection$$1) {
47996         var enabled = svgMapillarySigns.enabled,
47997             mapillary = getMapillary();
47998
47999         layer = selection$$1.selectAll('.layer-mapillary-signs')
48000             .data(mapillary ? [0] : []);
48001
48002         layer.exit()
48003             .remove();
48004
48005         layer = layer.enter()
48006             .append('g')
48007             .attr('class', 'layer-mapillary-signs')
48008             .style('display', enabled ? 'block' : 'none')
48009             .merge(layer);
48010
48011         if (enabled) {
48012             if (mapillary && ~~context.map().zoom() >= minZoom) {
48013                 editOn();
48014                 update();
48015                 mapillary.loadSigns(context, projection);
48016             } else {
48017                 editOff();
48018             }
48019         }
48020     }
48021
48022
48023     drawSigns.enabled = function(_) {
48024         if (!arguments.length) return svgMapillarySigns.enabled;
48025         svgMapillarySigns.enabled = _;
48026         if (svgMapillarySigns.enabled) {
48027             showLayer();
48028         } else {
48029             hideLayer();
48030         }
48031         dispatch$$1.call('change');
48032         return this;
48033     };
48034
48035
48036     drawSigns.supported = function() {
48037         var mapillary = getMapillary();
48038         return (mapillary && mapillary.signsSupported());
48039     };
48040
48041
48042     init();
48043     return drawSigns;
48044 }
48045
48046 function svgOsm() {
48047     return function drawOsm(selection) {
48048         var layers = selection.selectAll('.layer-osm')
48049             .data(['areas', 'lines', 'hit', 'halo', 'label']);
48050
48051         layers.enter()
48052             .append('g')
48053             .attr('class', function(d) { return 'layer-osm layer-' + d; });
48054     };
48055 }
48056
48057 function svgLayers(projection, context) {
48058     var dispatch$$1 = dispatch('change'),
48059         svg = select(null),
48060         layers = [
48061             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
48062             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
48063             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
48064             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
48065             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
48066         ];
48067
48068
48069     function drawLayers(selection$$1) {
48070         svg = selection$$1.selectAll('.surface')
48071             .data([0]);
48072
48073         svg = svg.enter()
48074             .append('svg')
48075             .attr('class', 'surface')
48076             .merge(svg);
48077
48078         var defs = svg.selectAll('.surface-defs')
48079             .data([0]);
48080
48081         defs.enter()
48082             .append('defs')
48083             .attr('class', 'surface-defs');
48084
48085         var groups = svg.selectAll('.data-layer')
48086             .data(layers);
48087
48088         groups.exit()
48089             .remove();
48090
48091         groups.enter()
48092             .append('g')
48093             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
48094             .merge(groups)
48095             .each(function(d) { select(this).call(d.layer); });
48096     }
48097
48098
48099     drawLayers.all = function() {
48100         return layers;
48101     };
48102
48103
48104     drawLayers.layer = function(id) {
48105         var obj = lodash.find(layers, function(o) {return o.id === id;});
48106         return obj && obj.layer;
48107     };
48108
48109
48110     drawLayers.only = function(what) {
48111         var arr = [].concat(what);
48112         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
48113         return this;
48114     };
48115
48116
48117     drawLayers.remove = function(what) {
48118         var arr = [].concat(what);
48119         arr.forEach(function(id) {
48120             layers = lodash.reject(layers, function(o) {return o.id === id;});
48121         });
48122         dispatch$$1.call('change');
48123         return this;
48124     };
48125
48126
48127     drawLayers.add = function(what) {
48128         var arr = [].concat(what);
48129         arr.forEach(function(obj) {
48130             if ('id' in obj && 'layer' in obj) {
48131                 layers.push(obj);
48132             }
48133         });
48134         dispatch$$1.call('change');
48135         return this;
48136     };
48137
48138
48139     drawLayers.dimensions = function(_) {
48140         if (!arguments.length) return utilGetDimensions(svg);
48141         utilSetDimensions(svg, _);
48142         return this;
48143     };
48144
48145
48146     return utilRebind(drawLayers, dispatch$$1, 'on');
48147 }
48148
48149 function svgLines$$1(projection) {
48150     var detected = utilDetect();
48151
48152     var highway_stack = {
48153         motorway: 0,
48154         motorway_link: 1,
48155         trunk: 2,
48156         trunk_link: 3,
48157         primary: 4,
48158         primary_link: 5,
48159         secondary: 6,
48160         tertiary: 7,
48161         unclassified: 8,
48162         residential: 9,
48163         service: 10,
48164         footway: 11
48165     };
48166
48167     function waystack(a, b) {
48168         var as = 0, bs = 0;
48169         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
48170         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
48171         return as - bs;
48172     }
48173
48174
48175     return function drawLines(selection$$1, graph, entities, filter) {
48176         var ways = [], pathdata = {}, onewaydata = {},
48177             getPath = svgPath(projection, graph);
48178
48179         for (var i = 0; i < entities.length; i++) {
48180             var entity = entities[i],
48181                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
48182             if (outer) {
48183                 ways.push(entity.mergeTags(outer.tags));
48184             } else if (entity.geometry(graph) === 'line') {
48185                 ways.push(entity);
48186             }
48187         }
48188
48189         ways = ways.filter(getPath);
48190
48191         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
48192
48193         lodash.forOwn(pathdata, function(v, k) {
48194             onewaydata[k] = lodash(v)
48195                 .filter(function(d) { return d.isOneWay(); })
48196                 .map(svgOneWaySegments(projection, graph, 35))
48197                 .flatten()
48198                 .valueOf();
48199         });
48200
48201         var layer = selection$$1.selectAll('.layer-lines');
48202
48203         var layergroup = layer
48204             .selectAll('g.layergroup')
48205             .data(sequence(-10, 11));
48206
48207         layergroup = layergroup.enter()
48208             .append('g')
48209             .attr('class', function(d) { return 'layergroup layer' + String(d); })
48210             .merge(layergroup);
48211
48212
48213         var linegroup = layergroup
48214             .selectAll('g.linegroup')
48215             .data(['shadow', 'casing', 'stroke']);
48216
48217         linegroup = linegroup.enter()
48218             .append('g')
48219             .attr('class', function(d) { return 'linegroup line-' + d; })
48220             .merge(linegroup);
48221
48222
48223         var lines = linegroup
48224             .selectAll('path')
48225             .filter(filter)
48226             .data(
48227                 function() { return pathdata[this.parentNode.__data__] || []; },
48228                 osmEntity$$1.key
48229             );
48230
48231         lines.exit()
48232             .remove();
48233
48234         // Optimization: call simple TagClasses only on enter selection. This
48235         // works because osmEntity.key is defined to include the entity v attribute.
48236         lines.enter()
48237             .append('path')
48238             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
48239             .call(svgTagClasses())
48240             .merge(lines)
48241                 .sort(waystack)
48242                 .attr('d', getPath)
48243                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
48244
48245
48246         var onewaygroup = layergroup
48247             .selectAll('g.onewaygroup')
48248             .data(['oneway']);
48249
48250         onewaygroup = onewaygroup.enter()
48251             .append('g')
48252             .attr('class', 'onewaygroup')
48253             .merge(onewaygroup);
48254
48255
48256         var oneways = onewaygroup
48257             .selectAll('path')
48258             .filter(filter)
48259             .data(
48260                 function() { return onewaydata[this.parentNode.__data__] || []; },
48261                 function(d) { return [d.id, d.index]; }
48262             );
48263
48264         oneways.exit()
48265             .remove();
48266
48267         oneways = oneways.enter()
48268             .append('path')
48269             .attr('class', 'oneway')
48270             .attr('marker-mid', 'url(#oneway-marker)')
48271             .merge(oneways)
48272             .attr('d', function(d) { return d.d; });
48273
48274         if (detected.ie) {
48275             oneways.each(function() { this.parentNode.insertBefore(this, this); });
48276         }
48277     };
48278 }
48279
48280 function svgMidpoints$$1(projection, context) {
48281
48282     return function drawMidpoints(selection, graph, entities, filter, extent) {
48283         var poly = extent.polygon(),
48284             midpoints = {};
48285
48286         for (var i = 0; i < entities.length; i++) {
48287             var entity = entities[i];
48288
48289             if (entity.type !== 'way')
48290                 continue;
48291             if (!filter(entity))
48292                 continue;
48293             if (context.selectedIDs().indexOf(entity.id) < 0)
48294                 continue;
48295
48296             var nodes = graph.childNodes(entity);
48297             for (var j = 0; j < nodes.length - 1; j++) {
48298
48299                 var a = nodes[j],
48300                     b = nodes[j + 1],
48301                     id = [a.id, b.id].sort().join('-');
48302
48303                 if (midpoints[id]) {
48304                     midpoints[id].parents.push(entity);
48305                 } else {
48306                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
48307                         var point = geoInterp(a.loc, b.loc, 0.5),
48308                             loc = null;
48309
48310                         if (extent.intersects(point)) {
48311                             loc = point;
48312                         } else {
48313                             for (var k = 0; k < 4; k++) {
48314                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
48315                                 if (point &&
48316                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
48317                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
48318                                 {
48319                                     loc = point;
48320                                     break;
48321                                 }
48322                             }
48323                         }
48324
48325                         if (loc) {
48326                             midpoints[id] = {
48327                                 type: 'midpoint',
48328                                 id: id,
48329                                 loc: loc,
48330                                 edge: [a.id, b.id],
48331                                 parents: [entity]
48332                             };
48333                         }
48334                     }
48335                 }
48336             }
48337         }
48338
48339
48340         function midpointFilter(d) {
48341             if (midpoints[d.id])
48342                 return true;
48343
48344             for (var i = 0; i < d.parents.length; i++) {
48345                 if (filter(d.parents[i])) {
48346                     return true;
48347                 }
48348             }
48349
48350             return false;
48351         }
48352
48353
48354         var layer = selection.selectAll('.layer-hit');
48355
48356         var groups = layer
48357             .selectAll('g.midpoint')
48358             .filter(midpointFilter)
48359             .data(lodash.values(midpoints), function(d) { return d.id; });
48360
48361         groups.exit()
48362             .remove();
48363
48364         var enter = groups.enter()
48365             .insert('g', ':first-child')
48366             .attr('class', 'midpoint');
48367
48368         enter.append('polygon')
48369             .attr('points', '-6,8 10,0 -6,-8')
48370             .attr('class', 'shadow');
48371
48372         enter.append('polygon')
48373             .attr('points', '-3,4 5,0 -3,-4')
48374             .attr('class', 'fill');
48375
48376         groups = groups
48377             .merge(enter)
48378             .attr('transform', function(d) {
48379                 var translate = svgPointTransform(projection),
48380                     a = graph.entity(d.edge[0]),
48381                     b = graph.entity(d.edge[1]),
48382                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
48383                 return translate(d) + ' rotate(' + angleVal + ')';
48384             })
48385             .call(svgTagClasses().tags(
48386                 function(d) { return d.parents[0].tags; }
48387             ));
48388
48389         // Propagate data bindings.
48390         groups.select('polygon.shadow');
48391         groups.select('polygon.fill');
48392
48393     };
48394 }
48395
48396 function svgOneWaySegments(projection, graph, dt) {
48397     return function(entity) {
48398         var a,
48399             b,
48400             i = 0,
48401             offset = dt,
48402             segments = [],
48403             clip = identity$5().clipExtent(projection.clipExtent()).stream,
48404             coordinates = graph.childNodes(entity).map(function(n) {
48405                 return n.loc;
48406             });
48407
48408         if (entity.tags.oneway === '-1') coordinates.reverse();
48409
48410         geoStream({
48411             type: 'LineString',
48412             coordinates: coordinates
48413         }, projection.stream(clip({
48414             lineStart: function() {},
48415             lineEnd: function() {
48416                 a = null;
48417             },
48418             point: function(x, y) {
48419                 b = [x, y];
48420
48421                 if (a) {
48422                     var span = geoEuclideanDistance(a, b) - offset;
48423
48424                     if (span >= 0) {
48425                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
48426                             dx = dt * Math.cos(angle),
48427                             dy = dt * Math.sin(angle),
48428                             p = [a[0] + offset * Math.cos(angle),
48429                                  a[1] + offset * Math.sin(angle)];
48430
48431                         var segment = 'M' + a[0] + ',' + a[1] +
48432                                       'L' + p[0] + ',' + p[1];
48433
48434                         for (span -= dt; span >= 0; span -= dt) {
48435                             p[0] += dx;
48436                             p[1] += dy;
48437                             segment += 'L' + p[0] + ',' + p[1];
48438                         }
48439
48440                         segment += 'L' + b[0] + ',' + b[1];
48441                         segments.push({id: entity.id, index: i, d: segment});
48442                     }
48443
48444                     offset = -span;
48445                     i++;
48446                 }
48447
48448                 a = b;
48449             }
48450         })));
48451
48452         return segments;
48453     };
48454 }
48455
48456 function svgPath(projection, graph, isArea) {
48457
48458     // Explanation of magic numbers:
48459     // "padding" here allows space for strokes to extend beyond the viewport,
48460     // so that the stroke isn't drawn along the edge of the viewport when
48461     // the shape is clipped.
48462     //
48463     // When drawing lines, pad viewport by 5px.
48464     // When drawing areas, pad viewport by 65px in each direction to allow
48465     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
48466
48467     var cache = {},
48468         padding = isArea ? 65 : 5,
48469         viewport = projection.clipExtent(),
48470         paddedExtent = [
48471             [viewport[0][0] - padding, viewport[0][1] - padding],
48472             [viewport[1][0] + padding, viewport[1][1] + padding]
48473         ],
48474         clip = identity$5().clipExtent(paddedExtent).stream,
48475         project = projection.stream,
48476         path$$1 = index$4()
48477             .projection({stream: function(output) { return project(clip(output)); }});
48478
48479     return function(entity) {
48480         if (entity.id in cache) {
48481             return cache[entity.id];
48482         } else {
48483             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
48484         }
48485     };
48486 }
48487
48488 function svgPoints$$1(projection, context) {
48489
48490     function markerPath(selection, klass) {
48491         selection
48492             .attr('class', klass)
48493             .attr('transform', 'translate(-8, -23)')
48494             .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');
48495     }
48496
48497     function sortY(a, b) {
48498         return b.loc[1] - a.loc[1];
48499     }
48500
48501
48502     return function drawPoints(selection, graph, entities, filter) {
48503         var wireframe = context.surface().classed('fill-wireframe'),
48504             points = wireframe ? [] : lodash.filter(entities, function(e) {
48505                 return e.geometry(graph) === 'point';
48506             });
48507
48508         points.sort(sortY);
48509
48510         var layer = selection.selectAll('.layer-hit');
48511
48512         var groups = layer.selectAll('g.point')
48513             .filter(filter)
48514             .data(points, osmEntity$$1.key);
48515
48516         groups.exit()
48517             .remove();
48518
48519         var enter = groups.enter()
48520             .append('g')
48521             .attr('class', function(d) { return 'node point ' + d.id; })
48522             .order();
48523
48524         enter.append('path')
48525             .call(markerPath, 'shadow');
48526
48527         enter.append('path')
48528             .call(markerPath, 'stroke');
48529
48530         enter.append('use')
48531             .attr('transform', 'translate(-5, -19)')
48532             .attr('class', 'icon')
48533             .attr('width', '11px')
48534             .attr('height', '11px');
48535
48536         groups = groups
48537             .merge(enter)
48538             .attr('transform', svgPointTransform(projection))
48539             .call(svgTagClasses());
48540
48541         // Selecting the following implicitly
48542         // sets the data (point entity) on the element
48543         groups.select('.shadow');
48544         groups.select('.stroke');
48545         groups.select('.icon')
48546             .attr('xlink:href', function(entity) {
48547                 var preset = context.presets().match(entity, graph);
48548                 return (preset && preset.icon) ? '#' + preset.icon + '-11' : '';
48549             });
48550     };
48551 }
48552
48553 function svgRelationMemberTags(graph) {
48554     return function(entity) {
48555         var tags = entity.tags;
48556         graph.parentRelations(entity).forEach(function(relation) {
48557             var type = relation.tags.type;
48558             if (type === 'multipolygon' || type === 'boundary') {
48559                 tags = lodash.extend({}, relation.tags, tags);
48560             }
48561         });
48562         return tags;
48563     };
48564 }
48565
48566 function svgTagClasses() {
48567     var primaries = [
48568             'building', 'highway', 'railway', 'waterway', 'aeroway',
48569             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48570             'leisure', 'military', 'place'
48571         ],
48572         statuses = [
48573             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48574             'razed', 'demolished', 'obliterated'
48575         ],
48576         secondaries = [
48577             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48578             'surface', 'tracktype', 'crossing'
48579         ],
48580         tagClassRe = /^tag-/,
48581         tags = function(entity) { return entity.tags; };
48582
48583
48584     var tagClasses = function(selection$$1) {
48585         selection$$1.each(function tagClassesEach(entity) {
48586             var value = this.className,
48587                 classes, primary, status;
48588
48589             if (value.baseVal !== undefined) value = value.baseVal;
48590
48591             classes = value.trim().split(/\s+/).filter(function(name) {
48592                 return name.length && !tagClassRe.test(name);
48593             }).join(' ');
48594
48595             var t = tags(entity), i, k, v;
48596
48597             // pick at most one primary classification tag..
48598             for (i = 0; i < primaries.length; i++) {
48599                 k = primaries[i];
48600                 v = t[k];
48601                 if (!v || v === 'no') continue;
48602
48603                 primary = k;
48604                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48605                     status = v;
48606                     classes += ' tag-' + k;
48607                 } else {
48608                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48609                 }
48610
48611                 break;
48612             }
48613
48614             // add at most one status tag, only if relates to primary tag..
48615             if (!status) {
48616                 for (i = 0; i < statuses.length; i++) {
48617                     k = statuses[i];
48618                     v = t[k];
48619                     if (!v || v === 'no') continue;
48620
48621                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48622                         status = k;
48623                     }
48624                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48625                         status = k;
48626                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48627                         status = k;
48628                         primary = v;
48629                         classes += ' tag-' + v;
48630                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48631
48632                     if (status) break;
48633                 }
48634             }
48635
48636             if (status) {
48637                 classes += ' tag-status tag-status-' + status;
48638             }
48639
48640             // add any secondary (structure) tags
48641             for (i = 0; i < secondaries.length; i++) {
48642                 k = secondaries[i];
48643                 v = t[k];
48644                 if (!v || v === 'no') continue;
48645                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48646             }
48647
48648             // For highways, look for surface tagging..
48649             if (primary === 'highway') {
48650                 var paved = (t.highway !== 'track');
48651                 for (k in t) {
48652                     v = t[k];
48653                     if (k in osmPavedTags) {
48654                         paved = !!osmPavedTags[k][v];
48655                         break;
48656                     }
48657                 }
48658                 if (!paved) {
48659                     classes += ' tag-unpaved';
48660                 }
48661             }
48662
48663             classes = classes.trim();
48664
48665             if (classes !== value) {
48666                 select(this).attr('class', classes);
48667             }
48668         });
48669     };
48670
48671
48672     tagClasses.tags = function(_) {
48673         if (!arguments.length) return tags;
48674         tags = _;
48675         return tagClasses;
48676     };
48677
48678     return tagClasses;
48679 }
48680
48681 function svgTurns(projection) {
48682
48683     return function drawTurns(selection, graph, turns) {
48684
48685         function key(turn) {
48686             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48687         }
48688
48689         function icon(turn) {
48690             var u = turn.u ? '-u' : '';
48691             if (!turn.restriction)
48692                 return '#turn-yes' + u;
48693             var restriction = graph.entity(turn.restriction).tags.restriction;
48694             return '#turn-' +
48695                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48696         }
48697
48698         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48699             .data(turns, key);
48700
48701         groups.exit()
48702             .remove();
48703
48704
48705         var enter = groups.enter()
48706             .append('g')
48707             .attr('class', 'turn');
48708
48709         var nEnter = enter
48710             .filter(function (turn) { return !turn.u; });
48711
48712         nEnter.append('rect')
48713             .attr('transform', 'translate(-22, -12)')
48714             .attr('width', '44')
48715             .attr('height', '24');
48716
48717         nEnter.append('use')
48718             .attr('transform', 'translate(-22, -12)')
48719             .attr('width', '44')
48720             .attr('height', '24');
48721
48722
48723         var uEnter = enter
48724             .filter(function (turn) { return turn.u; });
48725
48726         uEnter.append('circle')
48727             .attr('r', '16');
48728
48729         uEnter.append('use')
48730             .attr('transform', 'translate(-16, -16)')
48731             .attr('width', '32')
48732             .attr('height', '32');
48733
48734
48735         groups = groups
48736             .merge(enter);
48737
48738         groups
48739             .attr('transform', function (turn) {
48740                 var v = graph.entity(turn.via.node),
48741                     t = graph.entity(turn.to.node),
48742                     a = geoAngle(v, t, projection),
48743                     p = projection(v.loc),
48744                     r = turn.u ? 0 : 60;
48745
48746                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48747                     'rotate(' + a * 180 / Math.PI + ')';
48748             });
48749
48750         groups.select('use')
48751             .attr('xlink:href', icon);
48752
48753         groups.select('rect');
48754         groups.select('circle');
48755
48756         return this;
48757     };
48758 }
48759
48760 function svgVertices$$1(projection, context) {
48761     var radiuses = {
48762         //       z16-, z17, z18+, tagged
48763         shadow: [6,    7.5,   7.5,  11.5],
48764         stroke: [2.5,  3.5,   3.5,  7],
48765         fill:   [1,    1.5,   1.5,  1.5]
48766     };
48767
48768     var hover;
48769
48770
48771     function siblingAndChildVertices(ids, graph, extent$$1) {
48772         var vertices = {};
48773
48774         function addChildVertices(entity) {
48775             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48776                 var i;
48777                 if (entity.type === 'way') {
48778                     for (i = 0; i < entity.nodes.length; i++) {
48779                         addChildVertices(graph.entity(entity.nodes[i]));
48780                     }
48781                 } else if (entity.type === 'relation') {
48782                     for (i = 0; i < entity.members.length; i++) {
48783                         var member = context.hasEntity(entity.members[i].id);
48784                         if (member) {
48785                             addChildVertices(member);
48786                         }
48787                     }
48788                 } else if (entity.intersects(extent$$1, graph)) {
48789                     vertices[entity.id] = entity;
48790                 }
48791             }
48792         }
48793
48794         ids.forEach(function(id) {
48795             var entity = context.hasEntity(id);
48796             if (entity && entity.type === 'node') {
48797                 vertices[entity.id] = entity;
48798                 context.graph().parentWays(entity).forEach(function(entity) {
48799                     addChildVertices(entity);
48800                 });
48801             } else if (entity) {
48802                 addChildVertices(entity);
48803             }
48804         });
48805
48806         return vertices;
48807     }
48808
48809
48810     function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings) {
48811
48812         function icon(entity) {
48813             if (entity.id in icons) return icons[entity.id];
48814             icons[entity.id] =
48815                 entity.hasInterestingTags() &&
48816                 context.presets().match(entity, graph).icon;
48817             return icons[entity.id];
48818         }
48819
48820         function setClass(klass) {
48821             return function(entity) {
48822                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48823             };
48824         }
48825
48826         function setAttributes(selection$$1) {
48827             ['shadow','stroke','fill'].forEach(function(klass) {
48828                 var rads = radiuses[klass];
48829                 selection$$1.selectAll('.' + klass)
48830                     .each(function(entity) {
48831                         var i = z && icon(entity),
48832                             c = i ? 0.5 : 0,
48833                             r = rads[i ? 3 : z];
48834
48835                         // slightly increase the size of unconnected endpoints #3775
48836                         if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
48837                             r += 1.5;
48838                         }
48839
48840                         this.setAttribute('cx', c);
48841                         this.setAttribute('cy', -c);
48842                         this.setAttribute('r', r);
48843                         if (i && klass === 'fill') {
48844                             this.setAttribute('visibility', 'hidden');
48845                         } else {
48846                             this.removeAttribute('visibility');
48847                         }
48848                     });
48849             });
48850
48851             selection$$1.selectAll('use')
48852                 .each(function() {
48853                     if (z) {
48854                         this.removeAttribute('visibility');
48855                     } else {
48856                         this.setAttribute('visibility', 'hidden');
48857                     }
48858                 });
48859         }
48860
48861
48862         siblings = siblings || {};
48863
48864         var icons = {},
48865             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48866
48867         var groups = selection$$1
48868             .data(vertices, osmEntity$$1.key);
48869
48870         groups.exit()
48871             .remove();
48872
48873         var enter = groups.enter()
48874             .append('g')
48875             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48876
48877         enter.append('circle')
48878             .each(setClass('shadow'));
48879
48880         enter.append('circle')
48881             .each(setClass('stroke'));
48882
48883         // Vertices with icons get a `use`.
48884         enter.filter(function(d) { return icon(d); })
48885             .append('use')
48886             .attr('transform', 'translate(-5, -6)')
48887             .attr('xlink:href', function(d) { return '#' + icon(d) + '-11'; })
48888             .attr('width', '11px')
48889             .attr('height', '11px')
48890             .each(setClass('icon'));
48891
48892         // Vertices with tags get a fill.
48893         enter.filter(function(d) { return d.hasInterestingTags(); })
48894             .append('circle')
48895             .each(setClass('fill'));
48896
48897         groups
48898             .merge(enter)
48899             .attr('transform', svgPointTransform(projection))
48900             .classed('sibling', function(entity) { return entity.id in siblings; })
48901             .classed('shared', function(entity) { return graph.isShared(entity); })
48902             .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
48903             .call(setAttributes);
48904     }
48905
48906
48907     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48908         var siblings = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48909             wireframe = context.surface().classed('fill-wireframe'),
48910             vertices = [];
48911
48912         for (var i = 0; i < entities.length; i++) {
48913             var entity = entities[i],
48914                 geometry = entity.geometry(graph);
48915
48916             if (wireframe && geometry === 'point') {
48917                 vertices.push(entity);
48918                 continue;
48919             }
48920
48921             if (geometry !== 'vertex')
48922                 continue;
48923
48924             if (entity.id in siblings ||
48925                 entity.hasInterestingTags() ||
48926                 entity.isEndpoint(graph) ||
48927                 entity.isConnected(graph)) {
48928                 vertices.push(entity);
48929             }
48930         }
48931
48932         var layer = selection$$1.selectAll('.layer-hit');
48933         layer.selectAll('g.vertex.vertex-persistent')
48934             .filter(filter)
48935             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings);
48936
48937         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48938     }
48939
48940
48941     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48942         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48943         var layer = selection$$1.selectAll('.layer-hit');
48944
48945         layer.selectAll('g.vertex.vertex-hover')
48946             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48947     }
48948
48949
48950     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48951         if (target === hover) return;
48952         hover = target;
48953         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48954     };
48955
48956     return drawVertices;
48957 }
48958
48959 function behaviorEdit(context) {
48960
48961     function edit() {
48962         context.map()
48963             .minzoom(context.minEditableZoom());
48964     }
48965
48966
48967     edit.off = function() {
48968         context.map()
48969             .minzoom(0);
48970     };
48971
48972
48973     return edit;
48974 }
48975
48976 /*
48977    The hover behavior adds the `.hover` class on mouseover to all elements to which
48978    the identical datum is bound, and removes it on mouseout.
48979
48980    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
48981    representation may consist of several elements scattered throughout the DOM hierarchy.
48982    Only one of these elements can have the :hover pseudo-class, but all of them will
48983    have the .hover class.
48984  */
48985 function behaviorHover() {
48986     var dispatch$$1 = dispatch('hover'),
48987         selection$$1 = select(null),
48988         buttonDown,
48989         altDisables,
48990         target;
48991
48992
48993     function keydown() {
48994         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48995             dispatch$$1.call('hover', this, null);
48996             selection$$1.selectAll('.hover')
48997                 .classed('hover-suppressed', true)
48998                 .classed('hover', false);
48999         }
49000     }
49001
49002
49003     function keyup() {
49004         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
49005             dispatch$$1.call('hover', this, target ? target.id : null);
49006             selection$$1.selectAll('.hover-suppressed')
49007                 .classed('hover-suppressed', false)
49008                 .classed('hover', true);
49009         }
49010     }
49011
49012
49013     var hover = function(__) {
49014         selection$$1 = __;
49015
49016         selection$$1
49017             .on('mouseover.hover', mouseover)
49018             .on('mouseout.hover', mouseout)
49019             .on('mousedown.hover', mousedown);
49020
49021         select(window)
49022             .on('keydown.hover', keydown)
49023             .on('keyup.hover', keyup);
49024
49025
49026         function mouseover() {
49027             if (buttonDown) return;
49028             var target = event.target;
49029             enter(target ? target.__data__ : null);
49030         }
49031
49032
49033         function mouseout() {
49034             if (buttonDown) return;
49035             var target = event.relatedTarget;
49036             enter(target ? target.__data__ : null);
49037         }
49038
49039
49040         function mousedown() {
49041             buttonDown = true;
49042             select(window)
49043                 .on('mouseup.hover', mouseup, true);
49044         }
49045
49046
49047         function mouseup() {
49048             buttonDown = false;
49049             select(window)
49050                 .on('mouseup.hover', null, true);
49051         }
49052
49053
49054         function enter(d) {
49055             if (d === target) return;
49056             target = d;
49057
49058             selection$$1.selectAll('.hover')
49059                 .classed('hover', false);
49060             selection$$1.selectAll('.hover-suppressed')
49061                 .classed('hover-suppressed', false);
49062
49063             if (target instanceof osmEntity$$1) {
49064                 var selector$$1 = '.' + target.id;
49065
49066                 if (target.type === 'relation') {
49067                     target.members.forEach(function(member) {
49068                         selector$$1 += ', .' + member.id;
49069                     });
49070                 }
49071
49072                 var suppressed = altDisables && event && event.altKey;
49073
49074                 selection$$1.selectAll(selector$$1)
49075                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
49076
49077                 dispatch$$1.call('hover', this, target.id);
49078             } else {
49079                 dispatch$$1.call('hover', this, null);
49080             }
49081         }
49082
49083     };
49084
49085
49086     hover.off = function(selection$$1) {
49087         selection$$1.selectAll('.hover')
49088             .classed('hover', false);
49089         selection$$1.selectAll('.hover-suppressed')
49090             .classed('hover-suppressed', false);
49091
49092         selection$$1
49093             .on('mouseover.hover', null)
49094             .on('mouseout.hover', null)
49095             .on('mousedown.hover', null);
49096
49097         select(window)
49098             .on('keydown.hover', null)
49099             .on('keyup.hover', null);
49100     };
49101
49102
49103     hover.altDisables = function(_) {
49104         if (!arguments.length) return altDisables;
49105         altDisables = _;
49106         return hover;
49107     };
49108
49109
49110     return utilRebind(hover, dispatch$$1, 'on');
49111 }
49112
49113 function behaviorTail() {
49114     var text$$1,
49115         container,
49116         xmargin = 25,
49117         tooltipSize = [0, 0],
49118         selectionSize = [0, 0];
49119
49120
49121     function tail(selection$$1) {
49122         if (!text$$1) return;
49123
49124         select(window)
49125             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
49126
49127         container = select(document.body)
49128             .append('div')
49129             .style('display', 'none')
49130             .attr('class', 'tail tooltip-inner');
49131
49132         container.append('div')
49133             .text(text$$1);
49134
49135         selection$$1
49136             .on('mousemove.tail', mousemove)
49137             .on('mouseenter.tail', mouseenter)
49138             .on('mouseleave.tail', mouseleave);
49139
49140         container
49141             .on('mousemove.tail', mousemove);
49142
49143         tooltipSize = utilGetDimensions(container);
49144         selectionSize = utilGetDimensions(selection$$1);
49145
49146
49147         function show() {
49148             container.style('display', 'block');
49149             tooltipSize = utilGetDimensions(container);
49150         }
49151
49152
49153         function mousemove() {
49154             if (container.style('display') === 'none') show();
49155             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
49156                 -tooltipSize[0] - xmargin : xmargin;
49157             container.classed('left', xoffset > 0);
49158             utilSetTransform(container, event.clientX + xoffset, event.clientY);
49159         }
49160
49161
49162         function mouseleave() {
49163             if (event.relatedTarget !== container.node()) {
49164                 container.style('display', 'none');
49165             }
49166         }
49167
49168
49169         function mouseenter() {
49170             if (event.relatedTarget !== container.node()) {
49171                 show();
49172             }
49173         }
49174     }
49175
49176
49177     tail.off = function(selection$$1) {
49178         if (!text$$1) return;
49179
49180         container
49181             .on('mousemove.tail', null)
49182             .remove();
49183
49184         selection$$1
49185             .on('mousemove.tail', null)
49186             .on('mouseenter.tail', null)
49187             .on('mouseleave.tail', null);
49188
49189         select(window)
49190             .on('resize.tail', null);
49191     };
49192
49193
49194     tail.text = function(_) {
49195         if (!arguments.length) return text$$1;
49196         text$$1 = _;
49197         return tail;
49198     };
49199
49200
49201     return tail;
49202 }
49203
49204 behaviorDraw.usedTails = {};
49205 behaviorDraw.disableSpace = false;
49206 behaviorDraw.lastSpace = null;
49207
49208
49209 function behaviorDraw(context) {
49210     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
49211             'clickNode', 'undo', 'cancel', 'finish'),
49212         keybinding = d3keybinding('draw'),
49213         hover = behaviorHover(context)
49214             .altDisables(true)
49215             .on('hover', context.ui().sidebar.hover),
49216         tail = behaviorTail(),
49217         edit = behaviorEdit(context),
49218         closeTolerance = 4,
49219         tolerance = 12,
49220         mouseLeave = false,
49221         lastMouse = null,
49222         cached = behaviorDraw;
49223
49224
49225     function datum() {
49226         if (event.altKey) return {};
49227
49228         if (event.type === 'keydown') {
49229             return (lastMouse && lastMouse.target.__data__) || {};
49230         } else {
49231             return event.target.__data__ || {};
49232         }
49233     }
49234
49235
49236     function mousedown() {
49237
49238         function point() {
49239             var p = context.container().node();
49240             return touchId !== null ? touches(p).filter(function(p) {
49241                 return p.identifier === touchId;
49242             })[0] : mouse(p);
49243         }
49244
49245         var element = select(this),
49246             touchId = event.touches ? event.changedTouches[0].identifier : null,
49247             t1 = +new Date(),
49248             p1 = point();
49249
49250         element.on('mousemove.draw', null);
49251
49252         select(window).on('mouseup.draw', function() {
49253             var t2 = +new Date(),
49254                 p2 = point(),
49255                 dist = geoEuclideanDistance(p1, p2);
49256
49257             element.on('mousemove.draw', mousemove);
49258             select(window).on('mouseup.draw', null);
49259
49260             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
49261                 // Prevent a quick second click
49262                 select(window).on('click.draw-block', function() {
49263                     event.stopPropagation();
49264                 }, true);
49265
49266                 context.map().dblclickEnable(false);
49267
49268                 window.setTimeout(function() {
49269                     context.map().dblclickEnable(true);
49270                     select(window).on('click.draw-block', null);
49271                 }, 500);
49272
49273                 click();
49274             }
49275         }, true);
49276     }
49277
49278
49279     function mousemove() {
49280         lastMouse = event;
49281         dispatch$$1.call('move', this, datum());
49282     }
49283
49284
49285     function mouseenter() {
49286         mouseLeave = false;
49287     }
49288
49289
49290     function mouseleave() {
49291         mouseLeave = true;
49292     }
49293
49294
49295     function click() {
49296         var d = datum();
49297         if (d.type === 'way') {
49298             var dims = context.map().dimensions(),
49299                 mouse$$1 = context.mouse(),
49300                 pad = 5,
49301                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
49302                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
49303
49304             if (trySnap) {
49305                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
49306                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
49307                 dispatch$$1.call('clickWay', this, choice.loc, edge);
49308             } else {
49309                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49310             }
49311
49312         } else if (d.type === 'node') {
49313             dispatch$$1.call('clickNode', this, d);
49314
49315         } else {
49316             dispatch$$1.call('click', this, context.map().mouseCoordinates());
49317         }
49318     }
49319
49320
49321     function space() {
49322         var currSpace = context.mouse();
49323         if (cached.disableSpace && cached.lastSpace) {
49324             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
49325             if (dist > tolerance) {
49326                 cached.disableSpace = false;
49327             }
49328         }
49329
49330         if (cached.disableSpace || mouseLeave || !lastMouse) return;
49331
49332         // user must move mouse or release space bar to allow another click
49333         cached.lastSpace = currSpace;
49334         cached.disableSpace = true;
49335
49336         select(window).on('keyup.space-block', function() {
49337             cached.disableSpace = false;
49338             select(window).on('keyup.space-block', null);
49339         });
49340
49341         event.preventDefault();
49342         click();
49343     }
49344
49345
49346     function backspace() {
49347         event.preventDefault();
49348         dispatch$$1.call('undo');
49349     }
49350
49351
49352     function del() {
49353         event.preventDefault();
49354         dispatch$$1.call('cancel');
49355     }
49356
49357
49358     function ret() {
49359         event.preventDefault();
49360         dispatch$$1.call('finish');
49361     }
49362
49363
49364     function draw(selection$$1) {
49365         context.install(hover);
49366         context.install(edit);
49367
49368         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49369             context.install(tail);
49370         }
49371
49372         keybinding
49373             .on('⌫', backspace)
49374             .on('⌦', del)
49375             .on('⎋', ret)
49376             .on('↩', ret)
49377             .on('space', space)
49378             .on('⌥space', space);
49379
49380         selection$$1
49381             .on('mouseenter.draw', mouseenter)
49382             .on('mouseleave.draw', mouseleave)
49383             .on('mousedown.draw', mousedown)
49384             .on('mousemove.draw', mousemove);
49385
49386         select(document)
49387             .call(keybinding);
49388
49389         return draw;
49390     }
49391
49392
49393     draw.off = function(selection$$1) {
49394         context.ui().sidebar.hover.cancel();
49395         context.uninstall(hover);
49396         context.uninstall(edit);
49397
49398         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49399             context.uninstall(tail);
49400             cached.usedTails[tail.text()] = true;
49401         }
49402
49403         selection$$1
49404             .on('mouseenter.draw', null)
49405             .on('mouseleave.draw', null)
49406             .on('mousedown.draw', null)
49407             .on('mousemove.draw', null);
49408
49409         select(window)
49410             .on('mouseup.draw', null);
49411             // note: keyup.space-block, click.draw-block should remain
49412
49413         select(document)
49414             .call(keybinding.off);
49415     };
49416
49417
49418     draw.tail = function(_) {
49419         tail.text(_);
49420         return draw;
49421     };
49422
49423
49424     return utilRebind(draw, dispatch$$1, 'on');
49425 }
49426
49427 function behaviorAddWay(context) {
49428     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
49429         draw = behaviorDraw(context);
49430
49431     var addWay = function(surface) {
49432         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
49433             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
49434             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
49435             .on('cancel', addWay.cancel)
49436             .on('finish', addWay.cancel);
49437
49438         context.map()
49439             .dblclickEnable(false);
49440
49441         surface.call(draw);
49442     };
49443
49444
49445     addWay.off = function(surface) {
49446         surface.call(draw.off);
49447     };
49448
49449
49450     addWay.cancel = function() {
49451         window.setTimeout(function() {
49452             context.map().dblclickEnable(true);
49453         }, 1000);
49454
49455         context.enter(modeBrowse(context));
49456     };
49457
49458
49459     addWay.tail = function(text$$1) {
49460         draw.tail(text$$1);
49461         return addWay;
49462     };
49463
49464
49465     return utilRebind(addWay, dispatch$$1, 'on');
49466 }
49467
49468 function behaviorBreathe() {
49469     var duration = 800,
49470         steps = 4,
49471         selector$$1 = '.selected.shadow, .selected .shadow',
49472         selected = select(null),
49473         classed = '',
49474         params = {},
49475         done = false,
49476         timer$$1;
49477
49478
49479     function ratchetyInterpolator(a, b, steps, units) {
49480         a = parseFloat(a);
49481         b = parseFloat(b);
49482         var sample = quantize$2()
49483             .domain([0, 1])
49484             .range(quantize$1(number$1(a, b), steps));
49485
49486         return function(t) {
49487             return String(sample(t)) + (units || '');
49488         };
49489     }
49490
49491
49492     function reset(selection$$1) {
49493         selection$$1
49494             .style('stroke-opacity', null)
49495             .style('stroke-width', null)
49496             .style('fill-opacity', null)
49497             .style('r', null);
49498     }
49499
49500
49501     function setAnimationParams(transition$$1, fromTo) {
49502         var toFrom = (fromTo === 'from' ? 'to' : 'from');
49503
49504         transition$$1
49505             .styleTween('stroke-opacity', function(d) {
49506                 return ratchetyInterpolator(
49507                     params[d.id][toFrom].opacity,
49508                     params[d.id][fromTo].opacity,
49509                     steps
49510                 );
49511             })
49512             .styleTween('stroke-width', function(d) {
49513                 return ratchetyInterpolator(
49514                     params[d.id][toFrom].width,
49515                     params[d.id][fromTo].width,
49516                     steps,
49517                     'px'
49518                 );
49519             })
49520             .styleTween('fill-opacity', function(d) {
49521                 return ratchetyInterpolator(
49522                     params[d.id][toFrom].opacity,
49523                     params[d.id][fromTo].opacity,
49524                     steps
49525                 );
49526             })
49527             .styleTween('r', function(d) {
49528                 return ratchetyInterpolator(
49529                     params[d.id][toFrom].width,
49530                     params[d.id][fromTo].width,
49531                     steps,
49532                     'px'
49533                 );
49534             });
49535     }
49536
49537
49538     function calcAnimationParams(selection$$1) {
49539         selection$$1
49540             .call(reset)
49541             .each(function(d) {
49542                 var s = select(this),
49543                     tag = s.node().tagName,
49544                     p = {'from': {}, 'to': {}},
49545                     opacity, width;
49546
49547                 // determine base opacity and width
49548                 if (tag === 'circle') {
49549                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
49550                     width = parseFloat(s.style('r') || 15.5);
49551                 } else {
49552                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49553                     width = parseFloat(s.style('stroke-width') || 10);
49554                 }
49555
49556                 // calculate from/to interpolation params..
49557                 p.tag = tag;
49558                 p.from.opacity = opacity * 0.6;
49559                 p.to.opacity = opacity * 1.25;
49560                 p.from.width = width * 0.9;
49561                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
49562                 params[d.id] = p;
49563             });
49564     }
49565
49566
49567     function run(surface, fromTo) {
49568         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49569             currSelected = surface.selectAll(selector$$1),
49570             currClassed = surface.attr('class');
49571
49572         if (done || currSelected.empty()) {
49573             selected.call(reset);
49574             return;
49575         }
49576
49577         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49578             selected.call(reset);
49579             classed = currClassed;
49580             selected = currSelected.call(calcAnimationParams);
49581         }
49582
49583         selected
49584             .transition()
49585             .duration(duration)
49586             .call(setAnimationParams, fromTo)
49587             .on('end', function() {
49588                 surface.call(run, toFrom);
49589             });
49590     }
49591
49592
49593     var breathe = function(surface) {
49594         done = false;
49595         timer$$1 = timer$1(function() {
49596             // wait for elements to actually become selected
49597             if (surface.selectAll(selector$$1).empty()) {
49598                 return false;
49599             }
49600
49601             surface.call(run, 'from');
49602             timer$$1.stop();
49603             return true;
49604         }, 20);
49605     };
49606
49607
49608     breathe.off = function() {
49609         done = true;
49610         if (timer$$1) {
49611             timer$$1.stop();
49612         }
49613         selected
49614             .interrupt()
49615             .call(reset);
49616     };
49617
49618
49619     return breathe;
49620 }
49621
49622 function behaviorCopy(context) {
49623     var keybinding = d3keybinding('copy');
49624
49625
49626     function groupEntities(ids, graph) {
49627         var entities = ids.map(function (id) { return graph.entity(id); });
49628         return lodash.extend({relation: [], way: [], node: []},
49629             lodash.groupBy(entities, function(entity) { return entity.type; }));
49630     }
49631
49632
49633     function getDescendants(id, graph, descendants) {
49634         var entity = graph.entity(id),
49635             i, children;
49636
49637         descendants = descendants || {};
49638
49639         if (entity.type === 'relation') {
49640             children = lodash.map(entity.members, 'id');
49641         } else if (entity.type === 'way') {
49642             children = entity.nodes;
49643         } else {
49644             children = [];
49645         }
49646
49647         for (i = 0; i < children.length; i++) {
49648             if (!descendants[children[i]]) {
49649                 descendants[children[i]] = true;
49650                 descendants = getDescendants(children[i], graph, descendants);
49651             }
49652         }
49653
49654         return descendants;
49655     }
49656
49657
49658     function doCopy() {
49659         event.preventDefault();
49660         if (context.inIntro()) return;
49661
49662         var graph = context.graph(),
49663             selected = groupEntities(context.selectedIDs(), graph),
49664             canCopy = [],
49665             skip = {},
49666             i, entity;
49667
49668         for (i = 0; i < selected.relation.length; i++) {
49669             entity = selected.relation[i];
49670             if (!skip[entity.id] && entity.isComplete(graph)) {
49671                 canCopy.push(entity.id);
49672                 skip = getDescendants(entity.id, graph, skip);
49673             }
49674         }
49675         for (i = 0; i < selected.way.length; i++) {
49676             entity = selected.way[i];
49677             if (!skip[entity.id]) {
49678                 canCopy.push(entity.id);
49679                 skip = getDescendants(entity.id, graph, skip);
49680             }
49681         }
49682         for (i = 0; i < selected.node.length; i++) {
49683             entity = selected.node[i];
49684             if (!skip[entity.id]) {
49685                 canCopy.push(entity.id);
49686             }
49687         }
49688
49689         context.copyIDs(canCopy);
49690     }
49691
49692
49693     function copy() {
49694         keybinding.on(uiCmd('⌘C'), doCopy);
49695         select(document).call(keybinding);
49696         return copy;
49697     }
49698
49699
49700     copy.off = function() {
49701         select(document).call(keybinding.off);
49702     };
49703
49704
49705     return copy;
49706 }
49707
49708 /*
49709     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49710
49711     * The `origin` function is expected to return an [x, y] tuple rather than an
49712       {x, y} object.
49713     * The events are `start`, `move`, and `end`.
49714       (https://github.com/mbostock/d3/issues/563)
49715     * The `start` event is not dispatched until the first cursor movement occurs.
49716       (https://github.com/mbostock/d3/pull/368)
49717     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49718       than `x`, `y`, `dx`, and `dy` properties.
49719     * The `end` event is not dispatched if no movement occurs.
49720     * An `off` function is available that unbinds the drag's internal event handlers.
49721     * Delegation is supported via the `delegate` function.
49722
49723  */
49724 function behaviorDrag() {
49725     var event$$1 = dispatch('start', 'move', 'end'),
49726         origin = null,
49727         selector$$1 = '',
49728         filter = null,
49729         event_, target, surface;
49730
49731
49732     function d3_eventCancel() {
49733         event.stopPropagation();
49734         event.preventDefault();
49735     }
49736
49737     function eventOf(thiz, argumentz) {
49738         return function(e1) {
49739             e1.target = drag$$1;
49740             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49741         };
49742     }
49743
49744     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49745         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49746             function () {
49747                 var selection$$1 = selection(),
49748                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49749                 selection$$1.style(d3_event_userSelectProperty, 'none');
49750                 return function () {
49751                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49752                 };
49753             } :
49754             function (type) {
49755                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49756                 return function () {
49757                     w.on('selectstart.' + type, null);
49758                 };
49759             };
49760
49761
49762     function dragstart() {
49763         target = this;
49764         event_ = eventOf(target, arguments);
49765
49766         var eventTarget = event.target,
49767             touchId = event.touches ? event.changedTouches[0].identifier : null,
49768             offset,
49769             origin_ = point(),
49770             started = false,
49771             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49772
49773         var w = select(window)
49774             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49775             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49776
49777         if (origin) {
49778             offset = origin.apply(target, arguments);
49779             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49780         } else {
49781             offset = [0, 0];
49782         }
49783
49784         if (touchId === null) event.stopPropagation();
49785
49786
49787         function point() {
49788             var p = surface || target.parentNode;
49789             return touchId !== null ? touches(p).filter(function(p) {
49790                 return p.identifier === touchId;
49791             })[0] : mouse(p);
49792         }
49793
49794
49795         function dragmove() {
49796             var p = point(),
49797                 dx = p[0] - origin_[0],
49798                 dy = p[1] - origin_[1];
49799
49800             if (dx === 0 && dy === 0)
49801                 return;
49802
49803             if (!started) {
49804                 started = true;
49805                 event_({
49806                     type: 'start'
49807                 });
49808             }
49809
49810             origin_ = p;
49811             d3_eventCancel();
49812
49813             event_({
49814                 type: 'move',
49815                 point: [p[0] + offset[0],  p[1] + offset[1]],
49816                 delta: [dx, dy]
49817             });
49818         }
49819
49820
49821         function dragend() {
49822             if (started) {
49823                 event_({
49824                     type: 'end'
49825                 });
49826
49827                 d3_eventCancel();
49828                 if (event.target === eventTarget) w.on('click.drag', click, true);
49829             }
49830
49831             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49832                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49833             selectEnable();
49834         }
49835
49836
49837         function click() {
49838             d3_eventCancel();
49839             w.on('click.drag', null);
49840         }
49841     }
49842
49843
49844     function drag$$1(selection$$1) {
49845         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49846             delegate = dragstart;
49847
49848         if (selector$$1) {
49849             delegate = function() {
49850                 var root = this,
49851                     target = event.target;
49852                 for (; target && target !== root; target = target.parentNode) {
49853                     if (target[matchesSelector](selector$$1) &&
49854                             (!filter || filter(target.__data__))) {
49855                         return dragstart.call(target, target.__data__);
49856                     }
49857                 }
49858             };
49859         }
49860
49861         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49862             .on('touchstart.drag' + selector$$1, delegate);
49863     }
49864
49865
49866     drag$$1.off = function(selection$$1) {
49867         selection$$1.on('mousedown.drag' + selector$$1, null)
49868             .on('touchstart.drag' + selector$$1, null);
49869     };
49870
49871
49872     drag$$1.delegate = function(_) {
49873         if (!arguments.length) return selector$$1;
49874         selector$$1 = _;
49875         return drag$$1;
49876     };
49877
49878
49879     drag$$1.filter = function(_) {
49880         if (!arguments.length) return origin;
49881         filter = _;
49882         return drag$$1;
49883     };
49884
49885
49886     drag$$1.origin = function (_) {
49887         if (!arguments.length) return origin;
49888         origin = _;
49889         return drag$$1;
49890     };
49891
49892
49893     drag$$1.cancel = function() {
49894         select(window)
49895             .on('mousemove.drag', null)
49896             .on('mouseup.drag', null);
49897         return drag$$1;
49898     };
49899
49900
49901     drag$$1.target = function() {
49902         if (!arguments.length) return target;
49903         target = arguments[0];
49904         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49905         return drag$$1;
49906     };
49907
49908
49909     drag$$1.surface = function() {
49910         if (!arguments.length) return surface;
49911         surface = arguments[0];
49912         return drag$$1;
49913     };
49914
49915
49916     return utilRebind(drag$$1, event$$1, 'on');
49917 }
49918
49919 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49920
49921     var way = context.entity(wayId),
49922         isArea = context.geometry(wayId) === 'area',
49923         finished = false,
49924         annotation = t((way.isDegenerate() ?
49925             'operations.start.annotation.' :
49926             'operations.continue.annotation.') + context.geometry(wayId)),
49927         draw = behaviorDraw(context),
49928         startIndex, start, end, segment;
49929
49930
49931     if (!isArea) {
49932         startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0;
49933         start = osmNode({ id: 'nStart', loc: context.entity(way.nodes[startIndex]).loc });
49934         end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
49935         segment = osmWay({ id: 'wTemp',
49936             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49937             tags: lodash.clone(way.tags)
49938         });
49939     } else {
49940         end = osmNode({ loc: context.map().mouseCoordinates() });
49941     }
49942
49943
49944     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49945     if (isArea) {
49946         fn(actionAddEntity(end),
49947             actionAddVertex(wayId, end.id)
49948         );
49949     } else {
49950         fn(actionAddEntity(start),
49951             actionAddEntity(end),
49952             actionAddEntity(segment)
49953         );
49954     }
49955
49956
49957     function move(datum) {
49958         var loc;
49959
49960         if (datum.type === 'node' && datum.id !== end.id) {
49961             loc = datum.loc;
49962
49963         } else if (datum.type === 'way') { // && (segment || datum.id !== segment.id)) {
49964             var dims = context.map().dimensions(),
49965                 mouse = context.mouse(),
49966                 pad = 5,
49967                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49968                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49969
49970             if (trySnap) {
49971                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
49972             }
49973         }
49974
49975         if (!loc) {
49976             loc = context.map().mouseCoordinates();
49977         }
49978
49979         context.replace(actionMoveNode(end.id, loc));
49980     }
49981
49982
49983     function undone() {
49984         finished = true;
49985         context.enter(modeBrowse(context));
49986     }
49987
49988
49989     function setActiveElements() {
49990         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
49991         context.surface().selectAll(utilEntitySelector(active))
49992             .classed('active', true);
49993     }
49994
49995
49996     var drawWay = function(surface) {
49997         draw.on('move', move)
49998             .on('click', drawWay.add)
49999             .on('clickWay', drawWay.addWay)
50000             .on('clickNode', drawWay.addNode)
50001             .on('undo', context.undo)
50002             .on('cancel', drawWay.cancel)
50003             .on('finish', drawWay.finish);
50004
50005         context.map()
50006             .dblclickEnable(false)
50007             .on('drawn.draw', setActiveElements);
50008
50009         setActiveElements();
50010
50011         surface.call(draw);
50012
50013         context.history()
50014             .on('undone.draw', undone);
50015     };
50016
50017
50018     drawWay.off = function(surface) {
50019         if (!finished)
50020             context.pop();
50021
50022         context.map()
50023             .on('drawn.draw', null);
50024
50025         surface.call(draw.off)
50026             .selectAll('.active')
50027             .classed('active', false);
50028
50029         context.history()
50030             .on('undone.draw', null);
50031     };
50032
50033
50034     function ReplaceTemporaryNode(newNode) {
50035         return function(graph) {
50036             if (isArea) {
50037                 return graph
50038                     .replace(way.addNode(newNode.id))
50039                     .remove(end);
50040             } else {
50041                 return graph
50042                     .replace(graph.entity(wayId).addNode(newNode.id, index))
50043                     .remove(end)
50044                     .remove(segment)
50045                     .remove(start);
50046             }
50047         };
50048     }
50049
50050
50051     // Accept the current position of the temporary node and continue drawing.
50052     drawWay.add = function(loc) {
50053         // prevent duplicate nodes
50054         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
50055         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
50056
50057         if (isArea) {
50058             context.replace(
50059                 actionMoveNode(end.id, loc),
50060                 annotation
50061             );
50062         } else {
50063             var newNode = osmNode({loc: loc});
50064             context.replace(
50065                 actionAddEntity(newNode),
50066                 ReplaceTemporaryNode(newNode),
50067                 annotation
50068             );
50069         }
50070
50071         finished = true;
50072         context.enter(mode);
50073     };
50074
50075
50076     // Connect the way to an existing way.
50077     drawWay.addWay = function(loc, edge) {
50078
50079         if (isArea) {
50080             context.perform(
50081                 actionAddMidpoint({ loc: loc, edge: edge}, end),
50082                 annotation
50083             );
50084         } else {
50085             var previousEdge = startIndex ?
50086                 [way.nodes[startIndex], way.nodes[startIndex - 1]] :
50087                 [way.nodes[0], way.nodes[1]];
50088
50089             // Avoid creating duplicate segments
50090             if (geoEdgeEqual(edge, previousEdge))
50091                 return;
50092
50093             var newNode = osmNode({ loc: loc });
50094             context.perform(
50095                 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
50096                 ReplaceTemporaryNode(newNode),
50097                 annotation
50098             );
50099         }
50100
50101         finished = true;
50102         context.enter(mode);
50103     };
50104
50105
50106     // Connect the way to an existing node and continue drawing.
50107     drawWay.addNode = function(node) {
50108         // Avoid creating duplicate segments
50109         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
50110
50111         context.perform(
50112             ReplaceTemporaryNode(node),
50113             annotation
50114         );
50115
50116         finished = true;
50117         context.enter(mode);
50118     };
50119
50120
50121     // Finish the draw operation, removing the temporary node. If the way has enough
50122     // nodes to be valid, it's selected. Otherwise, return to browse mode.
50123     drawWay.finish = function() {
50124         context.pop();
50125         finished = true;
50126
50127         window.setTimeout(function() {
50128             context.map().dblclickEnable(true);
50129         }, 1000);
50130
50131         if (context.hasEntity(wayId)) {
50132             context.enter(
50133                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
50134             );
50135         } else {
50136             context.enter(modeBrowse(context));
50137         }
50138     };
50139
50140
50141     // Cancel the draw operation and return to browse, deleting everything drawn.
50142     drawWay.cancel = function() {
50143         context.perform(
50144             utilFunctor(baseGraph),
50145             t('operations.cancel_draw.annotation'));
50146
50147         window.setTimeout(function() {
50148             context.map().dblclickEnable(true);
50149         }, 1000);
50150
50151         finished = true;
50152         context.enter(modeBrowse(context));
50153     };
50154
50155
50156     drawWay.tail = function(text) {
50157         draw.tail(text);
50158         return drawWay;
50159     };
50160
50161
50162     return drawWay;
50163 }
50164
50165 function behaviorHash(context) {
50166     var s0 = null, // cached window.location.hash
50167         lat = 90 - 1e-8; // allowable latitude range
50168
50169
50170     var parser = function(map$$1, s) {
50171         var q = utilStringQs(s);
50172         var args = (q.map || '').split('/').map(Number);
50173         if (args.length < 3 || args.some(isNaN)) {
50174             return true; // replace bogus hash
50175         } else if (s !== formatter(map$$1).slice(1)) {
50176             map$$1.centerZoom([args[2],
50177                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
50178         }
50179     };
50180
50181
50182     var formatter = function(map$$1) {
50183         var mode = context.mode(),
50184             center = map$$1.center(),
50185             zoom$$1 = map$$1.zoom(),
50186             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
50187             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
50188             newParams = {};
50189
50190         if (mode && mode.id === 'browse') {
50191             delete q.id;
50192         } else {
50193             var selected = context.selectedIDs().filter(function(id) {
50194                 return !context.entity(id).isNew();
50195             });
50196             if (selected.length) {
50197                 newParams.id = selected.join(',');
50198             }
50199         }
50200
50201         newParams.map = zoom$$1.toFixed(2) +
50202                 '/' + center[1].toFixed(precision) +
50203                 '/' + center[0].toFixed(precision);
50204
50205         return '#' + utilQsString(lodash.assign(q, newParams), true);
50206     };
50207
50208
50209     function update() {
50210         if (context.inIntro()) return;
50211         var s1 = formatter(context.map());
50212         if (s0 !== s1) {
50213             window.location.replace(s0 = s1);  // don't recenter the map!
50214         }
50215     }
50216
50217
50218     var throttledUpdate = lodash.throttle(update, 500);
50219
50220
50221     function hashchange() {
50222         if (window.location.hash === s0) return;  // ignore spurious hashchange events
50223         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
50224             update(); // replace bogus hash
50225         }
50226     }
50227
50228
50229     function hash() {
50230         context.map()
50231             .on('move.hash', throttledUpdate);
50232
50233         context
50234             .on('enter.hash', throttledUpdate);
50235
50236         select(window)
50237             .on('hashchange.hash', hashchange);
50238
50239         if (window.location.hash) {
50240             var q = utilStringQs(window.location.hash.substring(1));
50241             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
50242             if (q.comment) context.storage('comment', q.comment);
50243             hashchange();
50244             if (q.map) hash.hadHash = true;
50245         }
50246     }
50247
50248
50249     hash.off = function() {
50250         throttledUpdate.cancel();
50251
50252         context.map()
50253             .on('move.hash', null);
50254
50255         context
50256             .on('enter.hash', null);
50257
50258         select(window)
50259             .on('hashchange.hash', null);
50260
50261         window.location.hash = '';
50262     };
50263
50264
50265     return hash;
50266 }
50267
50268 function behaviorLasso(context) {
50269
50270     var behavior = function(selection$$1) {
50271         var lasso;
50272
50273
50274         function mousedown() {
50275             var button = 0;  // left
50276             if (event.button === button && event.shiftKey === true) {
50277                 lasso = null;
50278
50279                 select(window)
50280                     .on('mousemove.lasso', mousemove)
50281                     .on('mouseup.lasso', mouseup);
50282
50283                 event.stopPropagation();
50284             }
50285         }
50286
50287
50288         function mousemove() {
50289             if (!lasso) {
50290                 lasso = uiLasso(context);
50291                 context.surface().call(lasso);
50292             }
50293
50294             lasso.p(context.mouse());
50295         }
50296
50297
50298         function normalize(a, b) {
50299             return [
50300                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
50301                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
50302         }
50303
50304
50305         function lassoed() {
50306             if (!lasso) return [];
50307
50308             var graph = context.graph(),
50309                 bounds = lasso.extent().map(context.projection.invert),
50310                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
50311
50312             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
50313                 return entity.type === 'node' &&
50314                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
50315                     !context.features().isHidden(entity, graph, entity.geometry(graph));
50316             }), 'id');
50317         }
50318
50319
50320         function mouseup() {
50321             select(window)
50322                 .on('mousemove.lasso', null)
50323                 .on('mouseup.lasso', null);
50324
50325             if (!lasso) return;
50326
50327             var ids = lassoed();
50328             lasso.close();
50329
50330             if (ids.length) {
50331                 context.enter(modeSelect(context, ids));
50332             }
50333         }
50334
50335         selection$$1
50336             .on('mousedown.lasso', mousedown);
50337     };
50338
50339
50340     behavior.off = function(selection$$1) {
50341         selection$$1.on('mousedown.lasso', null);
50342     };
50343
50344
50345     return behavior;
50346 }
50347
50348 /* Creates a keybinding behavior for an operation */
50349 function behaviorOperation(context) {
50350     var which, keybinding;
50351
50352
50353     var behavior = function () {
50354         if (which) {
50355             keybinding = d3keybinding('behavior.key.' + which.id);
50356             keybinding.on(which.keys, function() {
50357                 event.preventDefault();
50358                 if (which.available() && !which.disabled() && !context.inIntro()) {
50359                     which();
50360                 }
50361             });
50362             select(document).call(keybinding);
50363         }
50364         return behavior;
50365     };
50366
50367
50368     behavior.off = function() {
50369         if (keybinding) {
50370             select(document).call(keybinding.off);
50371         }
50372     };
50373
50374
50375     behavior.which = function (_) {
50376         if (!arguments.length) return which;
50377         which = _;
50378         return behavior;
50379     };
50380
50381
50382     return behavior;
50383 }
50384
50385 function behaviorPaste(context) {
50386     var keybinding = d3keybinding('paste');
50387
50388     function omitTag(v, k) {
50389         return (
50390             k === 'phone' ||
50391             k === 'fax' ||
50392             k === 'email' ||
50393             k === 'website' ||
50394             k === 'url' ||
50395             k === 'note' ||
50396             k === 'description' ||
50397             k.indexOf('name') !== -1 ||
50398             k.indexOf('wiki') === 0 ||
50399             k.indexOf('addr:') === 0 ||
50400             k.indexOf('contact:') === 0
50401         );
50402     }
50403
50404
50405     function doPaste() {
50406         event.preventDefault();
50407         if (context.inIntro()) return;
50408
50409         var baseGraph = context.graph(),
50410             mouse$$1 = context.mouse(),
50411             projection = context.projection,
50412             viewport = geoExtent$$1(projection.clipExtent()).polygon();
50413
50414         if (!geoPointInPolygon(mouse$$1, viewport)) return;
50415
50416         var extent$$1 = geoExtent$$1(),
50417             oldIDs = context.copyIDs(),
50418             oldGraph = context.copyGraph(),
50419             newIDs = [];
50420
50421         if (!oldIDs.length) return;
50422
50423         var action = actionCopyEntities(oldIDs, oldGraph);
50424         context.perform(action);
50425
50426         var copies = action.copies();
50427         var originals = lodash.invert(lodash.mapValues(copies, 'id'));
50428         for (var id in copies) {
50429             var oldEntity = oldGraph.entity(id),
50430                 newEntity = copies[id];
50431
50432             extent$$1._extend(oldEntity.extent(oldGraph));
50433             context.perform(
50434                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
50435             );
50436
50437             // Exclude child nodes from newIDs if their parent way was also copied.
50438             var parents = context.graph().parentWays(newEntity),
50439                 parentCopied = false;
50440             for (var i = 0; i < parents.length; i++) {
50441                 if (originals[parents[i].id]) {
50442                     parentCopied = true;
50443                     break;
50444                 }
50445             }
50446
50447             if (!parentCopied) {
50448                 newIDs.push(newEntity.id);
50449             }
50450         }
50451
50452         // Put pasted objects where mouse pointer is..
50453         var center = projection(extent$$1.center()),
50454             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
50455
50456         context.perform(actionMove(newIDs, delta, projection));
50457         context.enter(modeMove$$1(context, newIDs, baseGraph));
50458     }
50459
50460
50461     function paste() {
50462         keybinding.on(uiCmd('⌘V'), doPaste);
50463         select(document).call(keybinding);
50464         return paste;
50465     }
50466
50467
50468     paste.off = function() {
50469         select(document).call(keybinding.off);
50470     };
50471
50472
50473     return paste;
50474 }
50475
50476 function behaviorSelect(context) {
50477
50478     function keydown() {
50479         if (event && event.shiftKey) {
50480             context.surface()
50481                 .classed('behavior-multiselect', true);
50482         }
50483     }
50484
50485
50486     function keyup() {
50487         if (!event || !event.shiftKey) {
50488             context.surface()
50489                 .classed('behavior-multiselect', false);
50490         }
50491     }
50492
50493
50494     function click() {
50495         var datum = event.target.__data__,
50496             lasso = select('#surface .lasso').node(),
50497             mode = context.mode();
50498
50499         if (datum.type === 'midpoint') {
50500             // do nothing
50501         } else if (!(datum instanceof osmEntity$$1)) {
50502             if (!event.shiftKey && !lasso && mode.id !== 'browse')
50503                 context.enter(modeBrowse(context));
50504
50505         } else if (!event.shiftKey && !lasso) {
50506             // Avoid re-entering Select mode with same entity.
50507             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
50508                 context.enter(modeSelect(context, [datum.id]));
50509             } else {
50510                 mode.suppressMenu(false).reselect();
50511             }
50512         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
50513             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
50514             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
50515
50516         } else {
50517             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
50518         }
50519     }
50520
50521
50522     var behavior = function(selection$$1) {
50523         select(window)
50524             .on('keydown.select', keydown)
50525             .on('keyup.select', keyup);
50526
50527         selection$$1.on('click.select', click);
50528
50529         keydown();
50530     };
50531
50532
50533     behavior.off = function(selection$$1) {
50534         select(window)
50535             .on('keydown.select', null)
50536             .on('keyup.select', null);
50537
50538         selection$$1.on('click.select', null);
50539
50540         keyup();
50541     };
50542
50543
50544     return behavior;
50545 }
50546
50547 function modeAddArea$$1(context) {
50548     var mode = {
50549         id: 'add-area',
50550         button: 'area',
50551         title: t('modes.add_area.title'),
50552         description: t('modes.add_area.description'),
50553         key: '3'
50554     };
50555
50556     var behavior = behaviorAddWay(context)
50557             .tail(t('modes.add_area.tail'))
50558             .on('start', start)
50559             .on('startFromWay', startFromWay)
50560             .on('startFromNode', startFromNode),
50561         defaultTags = { area: 'yes' };
50562
50563
50564     function actionClose(wayId) {
50565         return function (graph) {
50566             return graph.replace(graph.entity(wayId).close());
50567         };
50568     }
50569
50570
50571     function start(loc) {
50572         var graph = context.graph(),
50573             node = osmNode({ loc: loc }),
50574             way = osmWay({ tags: defaultTags });
50575
50576         context.perform(
50577             actionAddEntity(node),
50578             actionAddEntity(way),
50579             actionAddVertex(way.id, node.id),
50580             actionClose(way.id)
50581         );
50582
50583         context.enter(modeDrawArea(context, way.id, graph));
50584     }
50585
50586
50587     function startFromWay(loc, edge) {
50588         var graph = context.graph(),
50589             node = osmNode({ loc: loc }),
50590             way = osmWay({ tags: defaultTags });
50591
50592         context.perform(
50593             actionAddEntity(node),
50594             actionAddEntity(way),
50595             actionAddVertex(way.id, node.id),
50596             actionClose(way.id),
50597             actionAddMidpoint({ loc: loc, edge: edge }, node)
50598         );
50599
50600         context.enter(modeDrawArea(context, way.id, graph));
50601     }
50602
50603
50604     function startFromNode(node) {
50605         var graph = context.graph(),
50606             way = osmWay({ tags: defaultTags });
50607
50608         context.perform(
50609             actionAddEntity(way),
50610             actionAddVertex(way.id, node.id),
50611             actionClose(way.id)
50612         );
50613
50614         context.enter(modeDrawArea(context, way.id, graph));
50615     }
50616
50617
50618     mode.enter = function() {
50619         context.install(behavior);
50620     };
50621
50622
50623     mode.exit = function() {
50624         context.uninstall(behavior);
50625     };
50626
50627
50628     return mode;
50629 }
50630
50631 function modeAddLine$$1(context) {
50632     var mode = {
50633         id: 'add-line',
50634         button: 'line',
50635         title: t('modes.add_line.title'),
50636         description: t('modes.add_line.description'),
50637         key: '2'
50638     };
50639
50640     var behavior = behaviorAddWay(context)
50641         .tail(t('modes.add_line.tail'))
50642         .on('start', start)
50643         .on('startFromWay', startFromWay)
50644         .on('startFromNode', startFromNode);
50645
50646
50647     function start(loc) {
50648         var baseGraph = context.graph(),
50649             node = osmNode({ loc: loc }),
50650             way = osmWay();
50651
50652         context.perform(
50653             actionAddEntity(node),
50654             actionAddEntity(way),
50655             actionAddVertex(way.id, node.id)
50656         );
50657
50658         context.enter(modeDrawLine(context, way.id, baseGraph));
50659     }
50660
50661
50662     function startFromWay(loc, edge) {
50663         var baseGraph = context.graph(),
50664             node = osmNode({ loc: loc }),
50665             way = osmWay();
50666
50667         context.perform(
50668             actionAddEntity(node),
50669             actionAddEntity(way),
50670             actionAddVertex(way.id, node.id),
50671             actionAddMidpoint({ loc: loc, edge: edge }, node)
50672         );
50673
50674         context.enter(modeDrawLine(context, way.id, baseGraph));
50675     }
50676
50677
50678     function startFromNode(node) {
50679         var baseGraph = context.graph(),
50680             way = osmWay();
50681
50682         context.perform(
50683             actionAddEntity(way),
50684             actionAddVertex(way.id, node.id)
50685         );
50686
50687         context.enter(modeDrawLine(context, way.id, baseGraph));
50688     }
50689
50690
50691     mode.enter = function() {
50692         context.install(behavior);
50693     };
50694
50695
50696     mode.exit = function() {
50697         context.uninstall(behavior);
50698     };
50699
50700     return mode;
50701 }
50702
50703 function modeAddPoint$$1(context) {
50704     var mode = {
50705         id: 'add-point',
50706         button: 'point',
50707         title: t('modes.add_point.title'),
50708         description: t('modes.add_point.description'),
50709         key: '1'
50710     };
50711
50712     var behavior = behaviorDraw(context)
50713         .tail(t('modes.add_point.tail'))
50714         .on('click', add)
50715         .on('clickWay', addWay)
50716         .on('clickNode', addNode)
50717         .on('cancel', cancel)
50718         .on('finish', cancel);
50719
50720
50721     function add(loc) {
50722         var node = osmNode({ loc: loc });
50723
50724         context.perform(
50725             actionAddEntity(node),
50726             t('operations.add.annotation.point')
50727         );
50728
50729         context.enter(
50730             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50731         );
50732     }
50733
50734
50735     function addWay(loc) {
50736         add(loc);
50737     }
50738
50739
50740     function addNode(node) {
50741         add(node.loc);
50742     }
50743
50744
50745     function cancel() {
50746         context.enter(modeBrowse(context));
50747     }
50748
50749
50750     mode.enter = function() {
50751         context.install(behavior);
50752     };
50753
50754
50755     mode.exit = function() {
50756         context.uninstall(behavior);
50757     };
50758
50759
50760     return mode;
50761 }
50762
50763 function modeBrowse(context) {
50764     var mode = {
50765         button: 'browse',
50766         id: 'browse',
50767         title: t('modes.browse.title'),
50768         description: t('modes.browse.description')
50769     }, sidebar;
50770
50771     var behaviors = [
50772         behaviorPaste(context),
50773         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50774         behaviorSelect(context),
50775         behaviorLasso(context)
50776     ];
50777
50778
50779     mode.enter = function() {
50780         behaviors.forEach(function(behavior) {
50781             context.install(behavior);
50782         });
50783
50784         // Get focus on the body.
50785         if (document.activeElement && document.activeElement.blur) {
50786             document.activeElement.blur();
50787         }
50788
50789         if (sidebar) {
50790             context.ui().sidebar.show(sidebar);
50791         } else {
50792             context.ui().sidebar.select(null);
50793         }
50794     };
50795
50796
50797     mode.exit = function() {
50798         context.ui().sidebar.hover.cancel();
50799         behaviors.forEach(function(behavior) {
50800             context.uninstall(behavior);
50801         });
50802
50803         if (sidebar) {
50804             context.ui().sidebar.hide();
50805         }
50806     };
50807
50808
50809     mode.sidebar = function(_) {
50810         if (!arguments.length) return sidebar;
50811         sidebar = _;
50812         return mode;
50813     };
50814
50815
50816     return mode;
50817 }
50818
50819 function modeDragNode$$1(context) {
50820     var mode = {
50821         id: 'drag-node',
50822         button: 'browse'
50823     };
50824
50825     var nudgeInterval,
50826         activeIDs,
50827         wasMidpoint,
50828         isCancelled,
50829         lastLoc,
50830         selectedIDs = [],
50831         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50832         edit = behaviorEdit(context);
50833
50834
50835     function vecSub(a, b) {
50836         return [a[0] - b[0], a[1] - b[1]];
50837     }
50838
50839     function edge(point, size) {
50840         var pad = [30, 100, 30, 100],
50841             x = 0,
50842             y = 0;
50843
50844         if (point[0] > size[0] - pad[0])
50845             x = -10;
50846         if (point[0] < pad[2])
50847             x = 10;
50848         if (point[1] > size[1] - pad[1])
50849             y = -10;
50850         if (point[1] < pad[3])
50851             y = 10;
50852
50853         if (x || y) {
50854             return [x, y];
50855         } else {
50856             return null;
50857         }
50858     }
50859
50860
50861     function startNudge(entity, nudge) {
50862         if (nudgeInterval) window.clearInterval(nudgeInterval);
50863         nudgeInterval = window.setInterval(function() {
50864             context.pan(nudge);
50865             doMove(entity, nudge);
50866         }, 50);
50867     }
50868
50869
50870     function stopNudge() {
50871         if (nudgeInterval) window.clearInterval(nudgeInterval);
50872         nudgeInterval = null;
50873     }
50874
50875
50876     function moveAnnotation(entity) {
50877         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50878     }
50879
50880
50881     function connectAnnotation(entity) {
50882         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50883     }
50884
50885
50886     function origin(entity) {
50887         return context.projection(entity.loc);
50888     }
50889
50890
50891     function start(entity) {
50892         wasMidpoint = entity.type === 'midpoint';
50893
50894         // Things allowed to be dragged include:
50895         // - midpoints
50896         // - nodes that are selected
50897         // - vertices that are selected
50898         // - vertices classed 'sibling' which includes (see svg/vertices.js)
50899         //   - children of selected ways or multipolygons
50900         //   - vertices sharing a way with selected vertices
50901         var selector$$1 = 'g.node.point.selected.' + entity.id +
50902             ', g.vertex-persistent.selected.' + entity.id +
50903             ', g.vertex-persistent.sibling.' + entity.id;
50904
50905         var isDraggable = wasMidpoint || !select(selector$$1).empty();
50906
50907         isCancelled = event.sourceEvent.shiftKey || !isDraggable ||
50908             context.features().hasHiddenConnections(entity, context.graph());
50909
50910         if (isCancelled) {
50911             return behavior.cancel();
50912         }
50913
50914         if (wasMidpoint) {
50915             var midpoint = entity;
50916             entity = osmNode();
50917             context.perform(actionAddMidpoint(midpoint, entity));
50918
50919             var vertex = context.surface().selectAll('.' + entity.id);
50920             behavior.target(vertex.node(), entity);
50921
50922         } else {
50923             context.perform(actionNoop());
50924         }
50925
50926         // activeIDs generate no pointer events.  This prevents the node or vertex
50927         // being dragged from trying to connect to itself or its parent element.
50928         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50929         activeIDs.push(entity.id);
50930         setActiveElements();
50931
50932         context.enter(mode);
50933     }
50934
50935
50936     function datum() {
50937         var event$$1 = event && event.sourceEvent;
50938         if (!event$$1 || event$$1.altKey) {
50939             return {};
50940         } else {
50941             return event$$1.target.__data__ || {};
50942         }
50943     }
50944
50945
50946     function doMove(entity, nudge) {
50947         nudge = nudge || [0, 0];
50948
50949         var currPoint = (event && event.point) || context.projection(lastLoc),
50950             currMouse = vecSub(currPoint, nudge),
50951             loc = context.projection.invert(currMouse),
50952             d = datum();
50953
50954         if (d.type === 'node' && d.id !== entity.id) {
50955             loc = d.loc;
50956         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50957             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50958         }
50959
50960         context.replace(
50961             actionMoveNode(entity.id, loc),
50962             moveAnnotation(entity)
50963         );
50964
50965         lastLoc = loc;
50966     }
50967
50968
50969     function move(entity) {
50970         if (isCancelled) return;
50971         event.sourceEvent.stopPropagation();
50972         lastLoc = context.projection.invert(event.point);
50973
50974         doMove(entity);
50975         var nudge = edge(event.point, context.map().dimensions());
50976         if (nudge) startNudge(entity, nudge);
50977         else stopNudge();
50978     }
50979
50980
50981     function end(entity) {
50982         if (isCancelled) return;
50983
50984         var d = datum();
50985
50986         if (d.type === 'way') {
50987             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
50988             context.replace(
50989                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
50990                 connectAnnotation(d)
50991             );
50992
50993         } else if (d.type === 'node' && d.id !== entity.id) {
50994             context.replace(
50995                 actionConnect([d.id, entity.id]),
50996                 connectAnnotation(d)
50997             );
50998
50999         } else if (wasMidpoint) {
51000             context.replace(
51001                 actionNoop(),
51002                 t('operations.add.annotation.vertex')
51003             );
51004
51005         } else {
51006             context.replace(
51007                 actionNoop(),
51008                 moveAnnotation(entity)
51009             );
51010         }
51011
51012         var reselection = selectedIDs.filter(function(id) {
51013             return context.graph().hasEntity(id);
51014         });
51015
51016         if (reselection.length) {
51017             context.enter(modeSelect(context, reselection).suppressMenu(true));
51018         } else {
51019             context.enter(modeBrowse(context));
51020         }
51021     }
51022
51023
51024     function cancel() {
51025         behavior.cancel();
51026         context.enter(modeBrowse(context));
51027     }
51028
51029
51030     function setActiveElements() {
51031         context.surface().selectAll(utilEntitySelector(activeIDs))
51032             .classed('active', true);
51033     }
51034
51035
51036     var behavior = behaviorDrag()
51037         .delegate('g.node, g.point, g.midpoint')
51038         .surface(select('#map').node())
51039         .origin(origin)
51040         .on('start', start)
51041         .on('move', move)
51042         .on('end', end);
51043
51044
51045     mode.enter = function() {
51046         context.install(hover);
51047         context.install(edit);
51048
51049         context.history()
51050             .on('undone.drag-node', cancel);
51051
51052         context.map()
51053             .on('drawn.drag-node', setActiveElements);
51054
51055         setActiveElements();
51056     };
51057
51058
51059     mode.exit = function() {
51060         context.ui().sidebar.hover.cancel();
51061         context.uninstall(hover);
51062         context.uninstall(edit);
51063
51064         context.history()
51065             .on('undone.drag-node', null);
51066
51067         context.map()
51068             .on('drawn.drag-node', null);
51069
51070         context.surface()
51071             .selectAll('.active')
51072             .classed('active', false);
51073
51074         stopNudge();
51075     };
51076
51077
51078     mode.selectedIDs = function(_) {
51079         if (!arguments.length) return selectedIDs;
51080         selectedIDs = _;
51081         return mode;
51082     };
51083
51084
51085     mode.behavior = behavior;
51086
51087
51088     return mode;
51089 }
51090
51091 function modeDrawArea(context, wayId, baseGraph) {
51092     var mode = {
51093         button: 'area',
51094         id: 'draw-area'
51095     };
51096
51097     var behavior;
51098
51099
51100     mode.enter = function() {
51101         var way = context.entity(wayId);
51102
51103         behavior = behaviorDrawWay(context, wayId, undefined, mode, baseGraph)
51104             .tail(t('modes.draw_area.tail'));
51105
51106         var addNode = behavior.addNode;
51107
51108         behavior.addNode = function(node) {
51109             var length = way.nodes.length,
51110                 penultimate = length > 2 ? way.nodes[length - 2] : null;
51111
51112             if (node.id === way.first() || node.id === penultimate) {
51113                 behavior.finish();
51114             } else {
51115                 addNode(node);
51116             }
51117         };
51118
51119         context.install(behavior);
51120     };
51121
51122
51123     mode.exit = function() {
51124         context.uninstall(behavior);
51125     };
51126
51127
51128     mode.selectedIDs = function() {
51129         return [wayId];
51130     };
51131
51132
51133     return mode;
51134 }
51135
51136 function modeDrawLine(context, wayId, baseGraph, affix) {
51137     var mode = {
51138         button: 'line',
51139         id: 'draw-line'
51140     };
51141
51142     var behavior;
51143
51144
51145     mode.enter = function() {
51146         var way = context.entity(wayId),
51147             index = (affix === 'prefix') ? 0 : undefined,
51148             headId = (affix === 'prefix') ? way.first() : way.last();
51149
51150         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
51151             .tail(t('modes.draw_line.tail'));
51152
51153         var addNode = behavior.addNode;
51154
51155         behavior.addNode = function(node) {
51156             if (node.id === headId) {
51157                 behavior.finish();
51158             } else {
51159                 addNode(node);
51160             }
51161         };
51162
51163         context.install(behavior);
51164     };
51165
51166
51167     mode.exit = function() {
51168         context.uninstall(behavior);
51169     };
51170
51171
51172     mode.selectedIDs = function() {
51173         return [wayId];
51174     };
51175
51176
51177     return mode;
51178 }
51179
51180 function operationCircularize(selectedIDs, context) {
51181     var entityId = selectedIDs[0],
51182         entity = context.entity(entityId),
51183         extent = entity.extent(context.graph()),
51184         geometry = context.geometry(entityId),
51185         action = actionCircularize(entityId, context.projection);
51186
51187
51188     var operation = function() {
51189         context.perform(action, t('operations.circularize.annotation.' + geometry));
51190     };
51191
51192
51193     operation.available = function() {
51194         return selectedIDs.length === 1 &&
51195             entity.type === 'way' &&
51196             lodash.uniq(entity.nodes).length > 1;
51197     };
51198
51199
51200     operation.disabled = function() {
51201         var reason;
51202         if (extent.percentContainedIn(context.extent()) < 0.8) {
51203             reason = 'too_large';
51204         } else if (context.hasHiddenConnections(entityId)) {
51205             reason = 'connected_to_hidden';
51206         }
51207         return action.disabled(context.graph()) || reason;
51208     };
51209
51210
51211     operation.tooltip = function() {
51212         var disable = operation.disabled();
51213         return disable ?
51214             t('operations.circularize.' + disable) :
51215             t('operations.circularize.description.' + geometry);
51216     };
51217
51218
51219     operation.id = 'circularize';
51220     operation.keys = [t('operations.circularize.key')];
51221     operation.title = t('operations.circularize.title');
51222     operation.behavior = behaviorOperation(context).which(operation);
51223
51224     return operation;
51225 }
51226
51227 function operationContinue(selectedIDs, context) {
51228     var graph = context.graph(),
51229         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51230         geometries = lodash.extend({ line: [], vertex: [] },
51231             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51232         vertex = geometries.vertex[0];
51233
51234
51235     function candidateWays() {
51236         return graph.parentWays(vertex).filter(function(parent) {
51237             return parent.geometry(graph) === 'line' &&
51238                 !parent.isClosed() &&
51239                 parent.affix(vertex.id) &&
51240                 (geometries.line.length === 0 || geometries.line[0] === parent);
51241         });
51242     }
51243
51244
51245     var operation = function() {
51246         var candidate = candidateWays()[0];
51247         context.enter(
51248             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51249         );
51250     };
51251
51252
51253     operation.available = function() {
51254         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51255             !context.features().hasHiddenConnections(vertex, context.graph());
51256     };
51257
51258
51259     operation.disabled = function() {
51260         var candidates = candidateWays();
51261         if (candidates.length === 0)
51262             return 'not_eligible';
51263         if (candidates.length > 1)
51264             return 'multiple';
51265     };
51266
51267
51268     operation.tooltip = function() {
51269         var disable = operation.disabled();
51270         return disable ?
51271             t('operations.continue.' + disable) :
51272             t('operations.continue.description');
51273     };
51274
51275
51276     operation.id = 'continue';
51277     operation.keys = [t('operations.continue.key')];
51278     operation.title = t('operations.continue.title');
51279     operation.behavior = behaviorOperation(context).which(operation);
51280
51281     return operation;
51282 }
51283
51284 function operationDelete(selectedIDs, context) {
51285     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51286         action = actionDeleteMultiple(selectedIDs);
51287
51288
51289     var operation = function() {
51290         var annotation,
51291             nextSelectedID;
51292
51293         if (selectedIDs.length > 1) {
51294             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51295
51296         } else {
51297             var id = selectedIDs[0],
51298                 entity = context.entity(id),
51299                 geometry = context.geometry(id),
51300                 parents = context.graph().parentWays(entity),
51301                 parent = parents[0];
51302
51303             annotation = t('operations.delete.annotation.' + geometry);
51304
51305             // Select the next closest node in the way.
51306             if (geometry === 'vertex' && parent.nodes.length > 2) {
51307                 var nodes = parent.nodes,
51308                     i = nodes.indexOf(id);
51309
51310                 if (i === 0) {
51311                     i++;
51312                 } else if (i === nodes.length - 1) {
51313                     i--;
51314                 } else {
51315                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51316                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51317                     i = a < b ? i - 1 : i + 1;
51318                 }
51319
51320                 nextSelectedID = nodes[i];
51321             }
51322         }
51323
51324         context.perform(action, annotation);
51325
51326         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51327             context.enter(
51328                 modeSelect(context, [nextSelectedID]).follow(true).suppressMenu(true)
51329             );
51330         } else {
51331             context.enter(modeBrowse(context));
51332         }
51333
51334     };
51335
51336
51337     operation.available = function() {
51338         return true;
51339     };
51340
51341
51342     operation.disabled = function() {
51343         var reason;
51344         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51345             reason = 'connected_to_hidden';
51346         } else if (lodash.some(selectedIDs, protectedMember)) {
51347             reason = 'part_of_relation';
51348         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51349             reason = 'incomplete_relation';
51350         }
51351         return reason;
51352
51353         function incompleteRelation(id) {
51354             var entity = context.entity(id);
51355             return entity.type === 'relation' && !entity.isComplete(context.graph());
51356         }
51357
51358         function protectedMember(id) {
51359             var entity = context.entity(id);
51360             if (entity.type !== 'way') return false;
51361
51362             var parents = context.graph().parentRelations(entity);
51363             for (var i = 0; i < parents.length; i++) {
51364                 var parent = parents[i],
51365                     type = parent.tags.type,
51366                     role = parent.memberById(id).role || 'outer';
51367                 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
51368                     return true;
51369                 }
51370             }
51371             return false;
51372         }
51373
51374     };
51375
51376
51377     operation.tooltip = function() {
51378         var disable = operation.disabled();
51379         return disable ?
51380             t('operations.delete.' + disable + '.' + multi) :
51381             t('operations.delete.description' + '.' + multi);
51382     };
51383
51384
51385     operation.id = 'delete';
51386     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51387     operation.title = t('operations.delete.title');
51388     operation.behavior = behaviorOperation(context).which(operation);
51389
51390     return operation;
51391 }
51392
51393 function operationDisconnect(selectedIDs, context) {
51394     var vertices = lodash.filter(selectedIDs, function(entityId) {
51395         return context.geometry(entityId) === 'vertex';
51396     });
51397
51398     var entityId = vertices[0],
51399         action = actionDisconnect(entityId);
51400
51401     if (selectedIDs.length > 1) {
51402         action.limitWays(lodash.without(selectedIDs, entityId));
51403     }
51404
51405
51406     var operation = function() {
51407         context.perform(action, t('operations.disconnect.annotation'));
51408     };
51409
51410
51411     operation.available = function() {
51412         return vertices.length === 1;
51413     };
51414
51415
51416     operation.disabled = function() {
51417         var reason;
51418         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51419             reason = 'connected_to_hidden';
51420         }
51421         return action.disabled(context.graph()) || reason;
51422     };
51423
51424
51425     operation.tooltip = function() {
51426         var disable = operation.disabled();
51427         return disable ?
51428             t('operations.disconnect.' + disable) :
51429             t('operations.disconnect.description');
51430     };
51431
51432
51433     operation.id = 'disconnect';
51434     operation.keys = [t('operations.disconnect.key')];
51435     operation.title = t('operations.disconnect.title');
51436     operation.behavior = behaviorOperation(context).which(operation);
51437
51438     return operation;
51439 }
51440
51441 function operationMerge(selectedIDs, context) {
51442     var join = actionJoin(selectedIDs),
51443         merge = actionMerge(selectedIDs),
51444         mergePolygon = actionMergePolygon(selectedIDs);
51445
51446     var operation = function() {
51447         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51448             action;
51449
51450         if (!join.disabled(context.graph())) {
51451             action = join;
51452         } else if (!merge.disabled(context.graph())) {
51453             action = merge;
51454         } else {
51455             action = mergePolygon;
51456         }
51457
51458         context.perform(action, annotation);
51459         var ids = selectedIDs.filter(function(id) {
51460             var entity = context.hasEntity(id);
51461             return entity && entity.type !== 'node';
51462         });
51463         context.enter(modeSelect(context, ids).suppressMenu(true));
51464     };
51465
51466
51467     operation.available = function() {
51468         return selectedIDs.length >= 2;
51469     };
51470
51471
51472     operation.disabled = function() {
51473         return join.disabled(context.graph()) &&
51474             merge.disabled(context.graph()) &&
51475             mergePolygon.disabled(context.graph());
51476     };
51477
51478
51479     operation.tooltip = function() {
51480         var j = join.disabled(context.graph()),
51481             m = merge.disabled(context.graph()),
51482             p = mergePolygon.disabled(context.graph());
51483
51484         if (j === 'restriction' && m && p) {
51485             return t('operations.merge.restriction',
51486                 { relation: context.presets().item('type/restriction').name() });
51487         }
51488
51489         if (p === 'incomplete_relation' && j && m) {
51490             return t('operations.merge.incomplete_relation');
51491         }
51492
51493         if (j && m && p) {
51494             return t('operations.merge.' + j);
51495         }
51496
51497         return t('operations.merge.description');
51498     };
51499
51500
51501     operation.id = 'merge';
51502     operation.keys = [t('operations.merge.key')];
51503     operation.title = t('operations.merge.title');
51504     operation.behavior = behaviorOperation(context).which(operation);
51505
51506     return operation;
51507 }
51508
51509 function operationMove(selectedIDs, context) {
51510     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51511         extent = selectedIDs.reduce(function(extent, id) {
51512             return extent.extend(context.entity(id).extent(context.graph()));
51513         }, geoExtent$$1());
51514
51515
51516     var operation = function() {
51517         context.enter(modeMove$$1(context, selectedIDs));
51518     };
51519
51520
51521     operation.available = function() {
51522         return selectedIDs.length > 1 ||
51523             context.entity(selectedIDs[0]).type !== 'node';
51524     };
51525
51526
51527     operation.disabled = function() {
51528         var reason;
51529         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51530             reason = 'too_large';
51531         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51532             reason = 'connected_to_hidden';
51533         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51534             reason = 'incomplete_relation';
51535         }
51536         return reason;
51537
51538         function incompleteRelation(id) {
51539             var entity = context.entity(id);
51540             return entity.type === 'relation' && !entity.isComplete(context.graph());
51541         }
51542     };
51543
51544
51545     operation.tooltip = function() {
51546         var disable = operation.disabled();
51547         return disable ?
51548             t('operations.move.' + disable + '.' + multi) :
51549             t('operations.move.description.' + multi);
51550     };
51551
51552
51553     operation.id = 'move';
51554     operation.keys = [t('operations.move.key')];
51555     operation.title = t('operations.move.title');
51556     operation.behavior = behaviorOperation(context).which(operation);
51557
51558     return operation;
51559 }
51560
51561 function operationOrthogonalize(selectedIDs, context) {
51562     var entityId = selectedIDs[0],
51563         entity = context.entity(entityId),
51564         extent = entity.extent(context.graph()),
51565         geometry = context.geometry(entityId),
51566         action = actionOrthogonalize(entityId, context.projection);
51567
51568
51569     var operation = function() {
51570         context.perform(action, t('operations.orthogonalize.annotation.' + geometry));
51571     };
51572
51573
51574     operation.available = function() {
51575         return selectedIDs.length === 1 &&
51576             entity.type === 'way' &&
51577             entity.isClosed() &&
51578             lodash.uniq(entity.nodes).length > 2;
51579     };
51580
51581
51582     operation.disabled = function() {
51583         var reason;
51584         if (extent.percentContainedIn(context.extent()) < 0.8) {
51585             reason = 'too_large';
51586         } else if (context.hasHiddenConnections(entityId)) {
51587             reason = 'connected_to_hidden';
51588         }
51589         return action.disabled(context.graph()) || reason;
51590     };
51591
51592
51593     operation.tooltip = function() {
51594         var disable = operation.disabled();
51595         return disable ?
51596             t('operations.orthogonalize.' + disable) :
51597             t('operations.orthogonalize.description.' + geometry);
51598     };
51599
51600
51601     operation.id = 'orthogonalize';
51602     operation.keys = [t('operations.orthogonalize.key')];
51603     operation.title = t('operations.orthogonalize.title');
51604     operation.behavior = behaviorOperation(context).which(operation);
51605
51606     return operation;
51607 }
51608
51609 function operationReflectShort(selectedIDs, context) {
51610     return operationReflect(selectedIDs, context, 'short');
51611 }
51612
51613
51614 function operationReflectLong(selectedIDs, context) {
51615     return operationReflect(selectedIDs, context, 'long');
51616 }
51617
51618
51619 function operationReflect(selectedIDs, context, axis) {
51620     axis = axis || 'long';
51621     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51622         extent = selectedIDs.reduce(function(extent, id) {
51623             return extent.extend(context.entity(id).extent(context.graph()));
51624         }, geoExtent$$1());
51625
51626
51627     var operation = function() {
51628         var action = actionReflect(selectedIDs, context.projection)
51629             .useLongAxis(Boolean(axis === 'long'));
51630         context.perform(action, t('operations.reflect.annotation.' + axis + '.' + multi));
51631     };
51632
51633
51634     operation.available = function() {
51635         return lodash.some(selectedIDs, hasArea);
51636
51637         function hasArea(id) {
51638             var entity = context.entity(id);
51639             return (entity.type === 'way' && entity.isClosed()) ||
51640                 (entity.type ==='relation' && entity.isMultipolygon());
51641         }
51642     };
51643
51644
51645     operation.disabled = function() {
51646         var reason;
51647         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51648             reason = 'too_large';
51649         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51650             reason = 'connected_to_hidden';
51651         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51652             reason = 'incomplete_relation';
51653         }
51654         return reason;
51655
51656         function incompleteRelation(id) {
51657             var entity = context.entity(id);
51658             return entity.type === 'relation' && !entity.isComplete(context.graph());
51659         }
51660     };
51661
51662
51663     operation.tooltip = function() {
51664         var disable = operation.disabled();
51665         return disable ?
51666             t('operations.reflect.' + disable + '.' + multi) :
51667             t('operations.reflect.description.' + axis + '.' + multi);
51668     };
51669
51670
51671     operation.id = 'reflect-' + axis;
51672     operation.keys = [t('operations.reflect.key.' + axis)];
51673     operation.title = t('operations.reflect.title');
51674     operation.behavior = behaviorOperation(context).which(operation);
51675
51676     return operation;
51677 }
51678
51679 function operationReverse(selectedIDs, context) {
51680     var entityId = selectedIDs[0];
51681
51682     var operation = function() {
51683         context.perform(actionReverse(entityId), t('operations.reverse.annotation'));
51684     };
51685
51686
51687     operation.available = function() {
51688         return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
51689     };
51690
51691
51692     operation.disabled = function() {
51693         return false;
51694     };
51695
51696
51697     operation.tooltip = function() {
51698         return t('operations.reverse.description');
51699     };
51700
51701
51702     operation.id = 'reverse';
51703     operation.keys = [t('operations.reverse.key')];
51704     operation.title = t('operations.reverse.title');
51705     operation.behavior = behaviorOperation(context).which(operation);
51706
51707     return operation;
51708 }
51709
51710 function operationRotate(selectedIDs, context) {
51711     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51712         extent = selectedIDs.reduce(function(extent, id) {
51713             return extent.extend(context.entity(id).extent(context.graph()));
51714         }, geoExtent$$1());
51715
51716
51717     var operation = function() {
51718         context.enter(modeRotate$$1(context, selectedIDs));
51719     };
51720
51721
51722     operation.available = function() {
51723         return lodash.some(selectedIDs, hasArea);
51724
51725         function hasArea(id) {
51726             var entity = context.entity(id);
51727             return (entity.type === 'way' && entity.isClosed()) ||
51728                 (entity.type ==='relation' && entity.isMultipolygon());
51729         }
51730     };
51731
51732
51733     operation.disabled = function() {
51734         var reason;
51735         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51736             reason = 'too_large';
51737         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51738             reason = 'connected_to_hidden';
51739         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51740             reason = 'incomplete_relation';
51741         }
51742         return reason;
51743
51744         function incompleteRelation(id) {
51745             var entity = context.entity(id);
51746             return entity.type === 'relation' && !entity.isComplete(context.graph());
51747         }
51748     };
51749
51750
51751     operation.tooltip = function() {
51752         var disable = operation.disabled();
51753         return disable ?
51754             t('operations.rotate.' + disable + '.' + multi) :
51755             t('operations.rotate.description.' + multi);
51756     };
51757
51758
51759     operation.id = 'rotate';
51760     operation.keys = [t('operations.rotate.key')];
51761     operation.title = t('operations.rotate.title');
51762     operation.behavior = behaviorOperation(context).which(operation);
51763
51764     return operation;
51765 }
51766
51767 function operationSplit(selectedIDs, context) {
51768     var vertices = lodash.filter(selectedIDs, function(entityId) {
51769         return context.geometry(entityId) === 'vertex';
51770     });
51771
51772     var entityId = vertices[0],
51773         action = actionSplit(entityId);
51774
51775     if (selectedIDs.length > 1) {
51776         action.limitWays(lodash.without(selectedIDs, entityId));
51777     }
51778
51779
51780     var operation = function() {
51781         var annotation;
51782
51783         var ways = action.ways(context.graph());
51784         if (ways.length === 1) {
51785             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51786         } else {
51787             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51788         }
51789
51790         var difference = context.perform(action, annotation);
51791         context.enter(modeSelect(context, difference.extantIDs()));
51792     };
51793
51794
51795     operation.available = function() {
51796         return vertices.length === 1;
51797     };
51798
51799
51800     operation.disabled = function() {
51801         var reason;
51802         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51803             reason = 'connected_to_hidden';
51804         }
51805         return action.disabled(context.graph()) || reason;
51806     };
51807
51808
51809     operation.tooltip = function() {
51810         var disable = operation.disabled();
51811         if (disable) {
51812             return t('operations.split.' + disable);
51813         }
51814
51815         var ways = action.ways(context.graph());
51816         if (ways.length === 1) {
51817             return t('operations.split.description.' + context.geometry(ways[0].id));
51818         } else {
51819             return t('operations.split.description.multiple');
51820         }
51821     };
51822
51823
51824     operation.id = 'split';
51825     operation.keys = [t('operations.split.key')];
51826     operation.title = t('operations.split.title');
51827     operation.behavior = behaviorOperation(context).which(operation);
51828
51829     return operation;
51830 }
51831
51832 function operationStraighten(selectedIDs, context) {
51833     var entityId = selectedIDs[0],
51834         action = actionStraighten(entityId, context.projection);
51835
51836
51837     function operation() {
51838         context.perform(action, t('operations.straighten.annotation'));
51839     }
51840
51841
51842     operation.available = function() {
51843         var entity = context.entity(entityId);
51844         return selectedIDs.length === 1 &&
51845             entity.type === 'way' &&
51846             !entity.isClosed() &&
51847             lodash.uniq(entity.nodes).length > 2;
51848     };
51849
51850
51851     operation.disabled = function() {
51852         var reason;
51853         if (context.hasHiddenConnections(entityId)) {
51854             reason = 'connected_to_hidden';
51855         }
51856         return action.disabled(context.graph()) || reason;
51857     };
51858
51859
51860     operation.tooltip = function() {
51861         var disable = operation.disabled();
51862         return disable ?
51863             t('operations.straighten.' + disable) :
51864             t('operations.straighten.description');
51865     };
51866
51867
51868     operation.id = 'straighten';
51869     operation.keys = [t('operations.straighten.key')];
51870     operation.title = t('operations.straighten.title');
51871     operation.behavior = behaviorOperation(context).which(operation);
51872
51873     return operation;
51874 }
51875
51876
51877
51878 var Operations = Object.freeze({
51879         operationCircularize: operationCircularize,
51880         operationContinue: operationContinue,
51881         operationDelete: operationDelete,
51882         operationDisconnect: operationDisconnect,
51883         operationMerge: operationMerge,
51884         operationMove: operationMove,
51885         operationOrthogonalize: operationOrthogonalize,
51886         operationReflectShort: operationReflectShort,
51887         operationReflectLong: operationReflectLong,
51888         operationReverse: operationReverse,
51889         operationRotate: operationRotate,
51890         operationSplit: operationSplit,
51891         operationStraighten: operationStraighten
51892 });
51893
51894 function modeMove$$1(context, entityIDs, baseGraph) {
51895     var mode = {
51896         id: 'move',
51897         button: 'browse'
51898     };
51899
51900     var keybinding = d3keybinding('move'),
51901         behaviors = [
51902             behaviorEdit(context),
51903             operationCircularize(entityIDs, context).behavior,
51904             operationDelete(entityIDs, context).behavior,
51905             operationOrthogonalize(entityIDs, context).behavior,
51906             operationReflectLong(entityIDs, context).behavior,
51907             operationReflectShort(entityIDs, context).behavior,
51908             operationRotate(entityIDs, context).behavior
51909         ],
51910         annotation = entityIDs.length === 1 ?
51911             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
51912             t('operations.move.annotation.multiple'),
51913         prevGraph,
51914         cache,
51915         origin,
51916         nudgeInterval;
51917
51918
51919     function vecSub(a, b) {
51920         return [a[0] - b[0], a[1] - b[1]];
51921     }
51922
51923
51924     function edge(point, size) {
51925         var pad = [30, 100, 30, 100],
51926             x = 0,
51927             y = 0;
51928
51929         if (point[0] > size[0] - pad[0])
51930             x = -10;
51931         if (point[0] < pad[2])
51932             x = 10;
51933         if (point[1] > size[1] - pad[1])
51934             y = -10;
51935         if (point[1] < pad[3])
51936             y = 10;
51937
51938         if (x || y) return [x, y];
51939         else return null;
51940     }
51941
51942
51943     function doMove(nudge) {
51944         nudge = nudge || [0, 0];
51945
51946         var fn;
51947         if (prevGraph !== context.graph()) {
51948             cache = {};
51949             origin = context.map().mouseCoordinates();
51950             fn = context.perform;
51951         } else {
51952             fn = context.overwrite;
51953         }
51954
51955         var currMouse = context.mouse(),
51956             origMouse = context.projection(origin),
51957             delta = vecSub(vecSub(currMouse, origMouse), nudge);
51958
51959         fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
51960         prevGraph = context.graph();
51961     }
51962
51963
51964     function startNudge(nudge) {
51965         if (nudgeInterval) window.clearInterval(nudgeInterval);
51966         nudgeInterval = window.setInterval(function() {
51967             context.pan(nudge);
51968             doMove(nudge);
51969         }, 50);
51970     }
51971
51972
51973     function stopNudge() {
51974         if (nudgeInterval) window.clearInterval(nudgeInterval);
51975         nudgeInterval = null;
51976     }
51977
51978
51979     function move() {
51980         doMove();
51981         var nudge = edge(context.mouse(), context.map().dimensions());
51982         if (nudge) startNudge(nudge);
51983         else stopNudge();
51984     }
51985
51986
51987     function finish() {
51988         event.stopPropagation();
51989         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
51990         stopNudge();
51991     }
51992
51993
51994     function cancel() {
51995         if (baseGraph) {
51996             while (context.graph() !== baseGraph) context.pop();
51997             context.enter(modeBrowse(context));
51998         } else {
51999             context.pop();
52000             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52001         }
52002         stopNudge();
52003     }
52004
52005
52006     function undone() {
52007         context.enter(modeBrowse(context));
52008     }
52009
52010
52011     mode.enter = function() {
52012         origin = context.map().mouseCoordinates();
52013         prevGraph = null;
52014         cache = {};
52015
52016         behaviors.forEach(function(behavior) {
52017             context.install(behavior);
52018         });
52019
52020         context.surface()
52021             .on('mousemove.move', move)
52022             .on('click.move', finish);
52023
52024         context.history()
52025             .on('undone.move', undone);
52026
52027         keybinding
52028             .on('⎋', cancel)
52029             .on('↩', finish);
52030
52031         select(document)
52032             .call(keybinding);
52033     };
52034
52035
52036     mode.exit = function() {
52037         stopNudge();
52038
52039         behaviors.forEach(function(behavior) {
52040             context.uninstall(behavior);
52041         });
52042
52043         context.surface()
52044             .on('mousemove.move', null)
52045             .on('click.move', null);
52046
52047         context.history()
52048             .on('undone.move', null);
52049
52050         keybinding.off();
52051     };
52052
52053
52054     return mode;
52055 }
52056
52057 function modeRotate$$1(context, entityIDs) {
52058     var mode = {
52059         id: 'rotate',
52060         button: 'browse'
52061     };
52062
52063     var keybinding = d3keybinding('rotate'),
52064         behaviors = [
52065             behaviorEdit(context),
52066             operationCircularize(entityIDs, context).behavior,
52067             operationDelete(entityIDs, context).behavior,
52068             operationMove(entityIDs, context).behavior,
52069             operationOrthogonalize(entityIDs, context).behavior,
52070             operationReflectLong(entityIDs, context).behavior,
52071             operationReflectShort(entityIDs, context).behavior
52072         ],
52073         annotation = entityIDs.length === 1 ?
52074             t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
52075             t('operations.rotate.annotation.multiple'),
52076         prevGraph,
52077         prevAngle,
52078         prevTransform,
52079         pivot;
52080
52081
52082     function doRotate() {
52083         var fn;
52084         if (context.graph() !== prevGraph) {
52085             fn = context.perform;
52086         } else {
52087             fn = context.replace;
52088         }
52089
52090         // projection changed, recalculate pivot
52091         var projection = context.projection;
52092         var currTransform = projection.transform();
52093         if (!prevTransform ||
52094             currTransform.k !== prevTransform.k ||
52095             currTransform.x !== prevTransform.x ||
52096             currTransform.y !== prevTransform.y) {
52097
52098             var nodes = utilGetAllNodes(entityIDs, context.graph()),
52099                 points = nodes.map(function(n) { return projection(n.loc); });
52100
52101             pivot = d3polygonCentroid(d3polygonHull(points));
52102             prevAngle = undefined;
52103         }
52104
52105
52106         var currMouse = context.mouse(),
52107             currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
52108
52109         if (typeof prevAngle === 'undefined') prevAngle = currAngle;
52110         var delta = currAngle - prevAngle;
52111
52112         fn(actionRotate(entityIDs, pivot, delta, projection), annotation);
52113
52114         prevTransform = currTransform;
52115         prevAngle = currAngle;
52116         prevGraph = context.graph();
52117     }
52118
52119
52120     function finish() {
52121         event.stopPropagation();
52122         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52123     }
52124
52125
52126     function cancel() {
52127         context.pop();
52128         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52129     }
52130
52131
52132     function undone() {
52133         context.enter(modeBrowse(context));
52134     }
52135
52136
52137     mode.enter = function() {
52138         behaviors.forEach(function(behavior) {
52139             context.install(behavior);
52140         });
52141
52142         context.surface()
52143             .on('mousemove.rotate', doRotate)
52144             .on('click.rotate', finish);
52145
52146         context.history()
52147             .on('undone.rotate', undone);
52148
52149         keybinding
52150             .on('⎋', cancel)
52151             .on('↩', finish);
52152
52153         select(document)
52154             .call(keybinding);
52155     };
52156
52157
52158     mode.exit = function() {
52159         behaviors.forEach(function(behavior) {
52160             context.uninstall(behavior);
52161         });
52162
52163         context.surface()
52164             .on('mousemove.rotate', null)
52165             .on('click.rotate', null);
52166
52167         context.history()
52168             .on('undone.rotate', null);
52169
52170         keybinding.off();
52171     };
52172
52173
52174     return mode;
52175 }
52176
52177 function modeSave$$1(context) {
52178     var mode = {
52179         id: 'save'
52180     };
52181
52182     var ui = uiCommit(context)
52183             .on('cancel', cancel)
52184             .on('save', save);
52185
52186
52187     function cancel() {
52188         context.enter(modeBrowse(context));
52189     }
52190
52191
52192     function save(e, tryAgain) {
52193         function withChildNodes(ids, graph) {
52194             return lodash.uniq(lodash.reduce(ids, function(result, id) {
52195                 var e = graph.entity(id);
52196                 if (e.type === 'way') {
52197                     try {
52198                         var cn = graph.childNodes(e);
52199                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
52200                     } catch (err) {
52201                         /* eslint-disable no-console */
52202                         if (typeof console !== 'undefined') console.error(err);
52203                         /* eslint-enable no-console */
52204                     }
52205                 }
52206                 return result;
52207             }, lodash.clone(ids)));
52208         }
52209
52210         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
52211             history = context.history(),
52212             origChanges = history.changes(actionDiscardTags(history.difference())),
52213             localGraph = context.graph(),
52214             remoteGraph = coreGraph$$1(history.base(), true),
52215             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
52216             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
52217             toLoad = withChildNodes(toCheck, localGraph),
52218             conflicts = [],
52219             errors = [];
52220
52221         if (!tryAgain) history.perform(actionNoop());  // checkpoint
52222         context.container().call(loading);
52223
52224         if (toCheck.length) {
52225             context.connection().loadMultiple(toLoad, loaded);
52226         } else {
52227             finalize();
52228         }
52229
52230
52231         // Reload modified entities into an alternate graph and check for conflicts..
52232         function loaded(err, result) {
52233             if (errors.length) return;
52234
52235             if (err) {
52236                 errors.push({
52237                     msg: err.responseText,
52238                     details: [ t('save.status_code', { code: err.status }) ]
52239                 });
52240                 showErrors();
52241
52242             } else {
52243                 var loadMore = [];
52244                 lodash.each(result.data, function(entity) {
52245                     remoteGraph.replace(entity);
52246                     toLoad = lodash.without(toLoad, entity.id);
52247
52248                     // Because loadMultiple doesn't download /full like loadEntity,
52249                     // need to also load children that aren't already being checked..
52250                     if (!entity.visible) return;
52251                     if (entity.type === 'way') {
52252                         loadMore.push.apply(loadMore,
52253                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
52254                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
52255                         loadMore.push.apply(loadMore,
52256                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
52257                     }
52258                 });
52259
52260                 if (loadMore.length) {
52261                     toLoad.push.apply(toLoad, loadMore);
52262                     context.connection().loadMultiple(loadMore, loaded);
52263                 }
52264
52265                 if (!toLoad.length) {
52266                     checkConflicts();
52267                 }
52268             }
52269         }
52270
52271
52272         function checkConflicts() {
52273             function choice(id, text$$1, action) {
52274                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
52275             }
52276             function formatUser(d) {
52277                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
52278             }
52279             function entityName(entity) {
52280                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
52281             }
52282
52283             function compareVersions(local$$1, remote) {
52284                 if (local$$1.version !== remote.version) return false;
52285
52286                 if (local$$1.type === 'way') {
52287                     var children = lodash.union(local$$1.nodes, remote.nodes);
52288
52289                     for (var i = 0; i < children.length; i++) {
52290                         var a = localGraph.hasEntity(children[i]),
52291                             b = remoteGraph.hasEntity(children[i]);
52292
52293                         if (a && b && a.version !== b.version) return false;
52294                     }
52295                 }
52296
52297                 return true;
52298             }
52299
52300             lodash.each(toCheck, function(id) {
52301                 var local$$1 = localGraph.entity(id),
52302                     remote = remoteGraph.entity(id);
52303
52304                 if (compareVersions(local$$1, remote)) return;
52305
52306                 var action = actionMergeRemoteChanges,
52307                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
52308
52309                 history.replace(merge$$1);
52310
52311                 var mergeConflicts = merge$$1.conflicts();
52312                 if (!mergeConflicts.length) return;  // merged safely
52313
52314                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
52315                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
52316                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
52317                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
52318
52319                 conflicts.push({
52320                     id: id,
52321                     name: entityName(local$$1),
52322                     details: mergeConflicts,
52323                     chosen: 1,
52324                     choices: [
52325                         choice(id, keepMine, forceLocal),
52326                         choice(id, keepTheirs, forceRemote)
52327                     ]
52328                 });
52329             });
52330
52331             finalize();
52332         }
52333
52334
52335         function finalize() {
52336             if (conflicts.length) {
52337                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
52338                 showConflicts();
52339             } else if (errors.length) {
52340                 showErrors();
52341             } else {
52342                 var changes = history.changes(actionDiscardTags(history.difference()));
52343                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
52344                     context.connection().putChangeset(
52345                         changes,
52346                         context.version,
52347                         e.comment,
52348                         history.imageryUsed(),
52349                         function(err, changeset_id) {
52350                             if (err) {
52351                                 errors.push({
52352                                     msg: err.responseText,
52353                                     details: [ t('save.status_code', { code: err.status }) ]
52354                                 });
52355                                 showErrors();
52356                             } else {
52357                                 history.clearSaved();
52358                                 success(e, changeset_id);
52359                                 // Add delay to allow for postgres replication #1646 #2678
52360                                 window.setTimeout(function() {
52361                                     loading.close();
52362                                     context.flush();
52363                                 }, 2500);
52364                             }
52365                         });
52366                 } else {        // changes were insignificant or reverted by user
52367                     loading.close();
52368                     context.flush();
52369                     cancel();
52370                 }
52371             }
52372         }
52373
52374
52375         function showConflicts() {
52376             var selection$$1 = context.container()
52377                 .select('#sidebar')
52378                 .append('div')
52379                 .attr('class','sidebar-component');
52380
52381             loading.close();
52382
52383             selection$$1.call(uiConflicts(context)
52384                 .list(conflicts)
52385                 .on('download', function() {
52386                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
52387                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
52388                     win.focus();
52389                 })
52390                 .on('cancel', function() {
52391                     history.pop();
52392                     selection$$1.remove();
52393                 })
52394                 .on('save', function() {
52395                     for (var i = 0; i < conflicts.length; i++) {
52396                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
52397                             var entity = context.hasEntity(conflicts[i].id);
52398                             if (entity && entity.type === 'way') {
52399                                 var children = lodash.uniq(entity.nodes);
52400                                 for (var j = 0; j < children.length; j++) {
52401                                     history.replace(actionRevert(children[j]));
52402                                 }
52403                             }
52404                             history.replace(actionRevert(conflicts[i].id));
52405                         }
52406                     }
52407
52408                     selection$$1.remove();
52409                     save(e, true);
52410                 })
52411             );
52412         }
52413
52414
52415         function showErrors() {
52416             var selection$$1 = uiConfirm(context.container());
52417
52418             history.pop();
52419             loading.close();
52420
52421             selection$$1
52422                 .select('.modal-section.header')
52423                 .append('h3')
52424                 .text(t('save.error'));
52425
52426             addErrors(selection$$1, errors);
52427             selection$$1.okButton();
52428         }
52429
52430
52431         function addErrors(selection$$1, data) {
52432             var message = selection$$1
52433                 .select('.modal-section.message-text');
52434
52435             var items = message
52436                 .selectAll('.error-container')
52437                 .data(data);
52438
52439             var enter = items.enter()
52440                 .append('div')
52441                 .attr('class', 'error-container');
52442
52443             enter
52444                 .append('a')
52445                 .attr('class', 'error-description')
52446                 .attr('href', '#')
52447                 .classed('hide-toggle', true)
52448                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
52449                 .on('click', function() {
52450                     var error = select(this),
52451                         detail = select(this.nextElementSibling),
52452                         exp = error.classed('expanded');
52453
52454                     detail.style('display', exp ? 'none' : 'block');
52455                     error.classed('expanded', !exp);
52456
52457                     event.preventDefault();
52458                 });
52459
52460             var details = enter
52461                 .append('div')
52462                 .attr('class', 'error-detail-container')
52463                 .style('display', 'none');
52464
52465             details
52466                 .append('ul')
52467                 .attr('class', 'error-detail-list')
52468                 .selectAll('li')
52469                 .data(function(d) { return d.details || []; })
52470                 .enter()
52471                 .append('li')
52472                 .attr('class', 'error-detail-item')
52473                 .text(function(d) { return d; });
52474
52475             items.exit()
52476                 .remove();
52477         }
52478
52479     }
52480
52481
52482     function success(e, changeset_id) {
52483         context.enter(modeBrowse(context)
52484             .sidebar(uiSuccess(context)
52485                 .changeset({
52486                     id: changeset_id,
52487                     comment: e.comment
52488                 })
52489                 .on('cancel', function() {
52490                     context.ui().sidebar.hide();
52491                 })
52492             )
52493         );
52494     }
52495
52496
52497     mode.enter = function() {
52498         function done() {
52499             context.ui().sidebar.show(ui);
52500         }
52501
52502         context.container().selectAll('#content')
52503             .attr('class', 'inactive');
52504
52505         if (context.connection().authenticated()) {
52506             done();
52507         } else {
52508             context.connection().authenticate(function(err) {
52509                 if (err) {
52510                     cancel();
52511                 } else {
52512                     done();
52513                 }
52514             });
52515         }
52516     };
52517
52518
52519     mode.exit = function() {
52520         context.container().selectAll('#content')
52521             .attr('class', 'active');
52522
52523         context.ui().sidebar.hide();
52524     };
52525
52526     return mode;
52527 }
52528
52529 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
52530 // For example, ⌘Z -> Ctrl+Z
52531 function uiCmd(code) {
52532     var detected = utilDetect();
52533
52534     if (detected.os === 'mac') {
52535         return code;
52536     }
52537
52538     if (detected.os === 'win') {
52539         if (code === '⌘⇧Z') return 'Ctrl+Y';
52540     }
52541
52542     var result = '',
52543         replacements = {
52544             '⌘': 'Ctrl',
52545             '⇧': 'Shift',
52546             '⌥': 'Alt',
52547             '⌫': 'Backspace',
52548             '⌦': 'Delete'
52549         };
52550
52551     for (var i = 0; i < code.length; i++) {
52552         if (code[i] in replacements) {
52553             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
52554         } else {
52555             result += code[i];
52556         }
52557     }
52558
52559     return result;
52560 }
52561
52562 var relatedParent;
52563
52564
52565 function modeSelect(context, selectedIDs) {
52566     var mode = {
52567         id: 'select',
52568         button: 'browse'
52569     };
52570
52571     var keybinding = d3keybinding('select'),
52572         timeout$$1 = null,
52573         behaviors = [
52574             behaviorCopy(context),
52575             behaviorPaste(context),
52576             behaviorBreathe(context),
52577             behaviorHover(context),
52578             behaviorSelect(context),
52579             behaviorLasso(context),
52580             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
52581         ],
52582         inspector,
52583         radialMenu,
52584         newFeature = false,
52585         suppressMenu = false,
52586         follow = false;
52587
52588
52589     var wrap = context.container()
52590         .select('.inspector-wrap');
52591
52592
52593     function singular() {
52594         if (selectedIDs.length === 1) {
52595             return context.hasEntity(selectedIDs[0]);
52596         }
52597     }
52598
52599
52600     function checkSelectedIDs() {
52601         var ids = [];
52602         if (Array.isArray(selectedIDs)) {
52603             ids = selectedIDs.filter(function(id) {
52604                 return context.hasEntity(id);
52605             });
52606         }
52607
52608         if (ids.length) {
52609             selectedIDs = ids;
52610         } else {
52611             context.enter(modeBrowse(context));
52612         }
52613         return !!ids.length;
52614     }
52615
52616
52617     // find the common parent ways for nextVertex, previousVertex
52618     function commonParents() {
52619         var graph = context.graph(),
52620             commonParents = [];
52621
52622         for (var i = 0; i < selectedIDs.length; i++) {
52623             var entity = context.hasEntity(selectedIDs[i]);
52624             if (!entity || entity.geometry(graph) !== 'vertex') {
52625                 return [];  // selection includes some not vertexes
52626             }
52627
52628             var currParents = lodash.map(graph.parentWays(entity), 'id');
52629             if (!commonParents.length) {
52630                 commonParents = currParents;
52631                 continue;
52632             }
52633
52634             commonParents = lodash.intersection(commonParents, currParents);
52635             if (!commonParents.length) {
52636                 return [];
52637             }
52638         }
52639
52640         return commonParents;
52641     }
52642
52643
52644     function singularParent() {
52645         var parents = commonParents();
52646         if (!parents || parents.length === 0) {
52647             relatedParent = null;
52648             return null;
52649         }
52650
52651         // relatedParent is used when we visit a vertex with multiple
52652         // parents, and we want to remember which parent line we started on.
52653
52654         if (parents.length === 1) {
52655             relatedParent = parents[0];  // remember this parent for later
52656             return relatedParent;
52657         }
52658
52659         if (parents.indexOf(relatedParent) !== -1) {
52660             return relatedParent;   // prefer the previously seen parent
52661         }
52662
52663         return parents[0];
52664     }
52665
52666
52667     function closeMenu() {
52668         if (radialMenu) {
52669             context.surface().call(radialMenu.close);
52670         }
52671     }
52672
52673
52674     function positionMenu() {
52675         if (suppressMenu || !radialMenu) { return; }
52676
52677         var entity = singular();
52678         if (entity && context.geometry(entity.id) === 'relation') {
52679             suppressMenu = true;
52680         } else if (entity && entity.type === 'node') {
52681             radialMenu.center(context.projection(entity.loc));
52682         } else {
52683             var point = context.mouse(),
52684                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
52685             if (geoPointInPolygon(point, viewport)) {
52686                 radialMenu.center(point);
52687             } else {
52688                 suppressMenu = true;
52689             }
52690         }
52691     }
52692
52693
52694     function showMenu() {
52695         closeMenu();
52696         if (!suppressMenu && radialMenu) {
52697             context.surface().call(radialMenu);
52698         }
52699     }
52700
52701
52702     function toggleMenu() {
52703         if (select('.radial-menu').empty()) {
52704             showMenu();
52705         } else {
52706             closeMenu();
52707         }
52708     }
52709
52710
52711     mode.selectedIDs = function() {
52712         return selectedIDs;
52713     };
52714
52715
52716     mode.reselect = function() {
52717         if (!checkSelectedIDs()) return;
52718
52719         var surfaceNode = context.surface().node();
52720         if (surfaceNode.focus) {   // FF doesn't support it
52721             surfaceNode.focus();
52722         }
52723
52724         positionMenu();
52725         showMenu();
52726     };
52727
52728
52729     mode.newFeature = function(_) {
52730         if (!arguments.length) return newFeature;
52731         newFeature = _;
52732         return mode;
52733     };
52734
52735
52736     mode.suppressMenu = function(_) {
52737         if (!arguments.length) return suppressMenu;
52738         suppressMenu = _;
52739         return mode;
52740     };
52741
52742
52743     mode.follow = function(_) {
52744         if (!arguments.length) return follow;
52745         follow = _;
52746         return mode;
52747     };
52748
52749
52750     mode.enter = function() {
52751
52752         function update() {
52753             closeMenu();
52754             checkSelectedIDs();
52755         }
52756
52757
52758         function dblclick() {
52759             var target = select(event.target),
52760                 datum = target.datum();
52761
52762             if (datum instanceof osmWay && !target.classed('fill')) {
52763                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
52764                     prev = datum.nodes[choice.index - 1],
52765                     next = datum.nodes[choice.index];
52766
52767                 context.perform(
52768                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
52769                     t('operations.add.annotation.vertex')
52770                 );
52771
52772                 event.preventDefault();
52773                 event.stopPropagation();
52774             } else if (datum.type === 'midpoint') {
52775                 context.perform(
52776                     actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
52777                     t('operations.add.annotation.vertex'));
52778
52779                 event.preventDefault();
52780                 event.stopPropagation();
52781             }
52782         }
52783
52784
52785         function selectElements(drawn) {
52786             if (!checkSelectedIDs()) return;
52787
52788             var surface = context.surface(),
52789                 entity = singular();
52790
52791             if (entity && context.geometry(entity.id) === 'relation') {
52792                 suppressMenu = true;
52793                 return;
52794             }
52795
52796             surface.selectAll('.related')
52797                 .classed('related', false);
52798
52799             singularParent();
52800             if (relatedParent) {
52801                 surface.selectAll(utilEntitySelector([relatedParent]))
52802                     .classed('related', true);
52803             }
52804
52805             var selection$$1 = context.surface()
52806                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
52807
52808             if (selection$$1.empty()) {
52809                 // Return to browse mode if selected DOM elements have
52810                 // disappeared because the user moved them out of view..
52811                 var source = event && event.type === 'zoom' && event.sourceEvent;
52812                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
52813                     context.enter(modeBrowse(context));
52814                 }
52815             } else {
52816                 selection$$1
52817                     .classed('selected', true);
52818             }
52819         }
52820
52821
52822         function esc() {
52823             if (!context.inIntro()) {
52824                 context.enter(modeBrowse(context));
52825             }
52826         }
52827
52828
52829         function firstVertex() {
52830             event.preventDefault();
52831             var parent = singularParent();
52832             if (parent) {
52833                 var way = context.entity(parent);
52834                 context.enter(
52835                     modeSelect(context, [way.first()]).follow(true).suppressMenu(true)
52836                 );
52837             }
52838         }
52839
52840
52841         function lastVertex() {
52842             event.preventDefault();
52843             var parent = singularParent();
52844             if (parent) {
52845                 var way = context.entity(parent);
52846                 context.enter(
52847                     modeSelect(context, [way.last()]).follow(true).suppressMenu(true)
52848                 );
52849             }
52850         }
52851
52852
52853         function previousVertex() {
52854             event.preventDefault();
52855             var parent = singularParent();
52856             if (!parent) return;
52857
52858             var way = context.entity(parent),
52859                 length = way.nodes.length,
52860                 curr = way.nodes.indexOf(selectedIDs[0]),
52861                 index = -1;
52862
52863             if (curr > 0) {
52864                 index = curr - 1;
52865             } else if (way.isClosed()) {
52866                 index = length - 2;
52867             }
52868
52869             if (index !== -1) {
52870                 context.enter(
52871                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52872                 );
52873             }
52874         }
52875
52876
52877         function nextVertex() {
52878             event.preventDefault();
52879             var parent = singularParent();
52880             if (!parent) return;
52881
52882             var way = context.entity(parent),
52883                 length = way.nodes.length,
52884                 curr = way.nodes.indexOf(selectedIDs[0]),
52885                 index = -1;
52886
52887             if (curr < length - 1) {
52888                 index = curr + 1;
52889             } else if (way.isClosed()) {
52890                 index = 0;
52891             }
52892
52893             if (index !== -1) {
52894                 context.enter(
52895                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52896                 );
52897             }
52898         }
52899
52900
52901         function nextParent() {
52902             event.preventDefault();
52903             var parents = lodash.uniq(commonParents());
52904             if (!parents || parents.length < 2) return;
52905
52906             var index = parents.indexOf(relatedParent);
52907             if (index < 0 || index > parents.length - 2) {
52908                 relatedParent = parents[0];
52909             } else {
52910                 relatedParent = parents[index + 1];
52911             }
52912
52913             var surface = context.surface();
52914             surface.selectAll('.related')
52915                 .classed('related', false);
52916
52917             if (relatedParent) {
52918                 surface.selectAll(utilEntitySelector([relatedParent]))
52919                     .classed('related', true);
52920             }
52921         }
52922
52923
52924         if (!checkSelectedIDs()) return;
52925
52926         var operations = lodash.without(values(Operations), operationDelete)
52927                 .map(function(o) { return o(selectedIDs, context); })
52928                 .filter(function(o) { return o.available(); });
52929
52930         operations.unshift(operationDelete(selectedIDs, context));
52931
52932         operations.forEach(function(operation) {
52933             if (operation.behavior) {
52934                 behaviors.push(operation.behavior);
52935             }
52936         });
52937
52938         behaviors.forEach(function(behavior) {
52939             context.install(behavior);
52940         });
52941
52942         keybinding
52943             .on(['[','pgup'], previousVertex)
52944             .on([']', 'pgdown'], nextVertex)
52945             .on([uiCmd('⌘['), 'home'], firstVertex)
52946             .on([uiCmd('⌘]'), 'end'], lastVertex)
52947             .on(['\\', 'pause'], nextParent)
52948             .on('⎋', esc, true)
52949             .on('space', toggleMenu);
52950
52951         select(document)
52952             .call(keybinding);
52953
52954         radialMenu = uiRadialMenu(context, operations);
52955
52956         context.ui().sidebar
52957             .select(singular() ? singular().id : null, newFeature);
52958
52959         context.history()
52960             .on('undone.select', update)
52961             .on('redone.select', update);
52962
52963         context.map()
52964             .on('move.select', closeMenu)
52965             .on('drawn.select', selectElements);
52966
52967         selectElements();
52968
52969         var show = event && !suppressMenu;
52970
52971         if (show) {
52972             positionMenu();
52973         }
52974
52975         if (follow) {
52976             var extent$$1 = geoExtent$$1(),
52977                 graph = context.graph();
52978             selectedIDs.forEach(function(id) {
52979                 var entity = context.entity(id);
52980                 extent$$1._extend(entity.extent(graph));
52981             });
52982
52983             var loc = extent$$1.center();
52984             context.map().centerEase(loc);
52985         }
52986
52987         timeout$$1 = window.setTimeout(function() {
52988             if (show) {
52989                 showMenu();
52990             }
52991
52992             context.surface()
52993                 .on('dblclick.select', dblclick);
52994         }, 200);
52995
52996         if (selectedIDs.length > 1) {
52997             var entities = uiSelectionList(context, selectedIDs);
52998             context.ui().sidebar.show(entities);
52999         }
53000     };
53001
53002
53003     mode.exit = function() {
53004         if (timeout$$1) window.clearTimeout(timeout$$1);
53005
53006         if (inspector) wrap.call(inspector.close);
53007
53008         behaviors.forEach(function(behavior) {
53009             context.uninstall(behavior);
53010         });
53011
53012         keybinding.off();
53013         closeMenu();
53014         radialMenu = undefined;
53015
53016         context.history()
53017             .on('undone.select', null)
53018             .on('redone.select', null);
53019
53020         var surface = context.surface();
53021
53022         surface
53023             .on('dblclick.select', null);
53024
53025         surface
53026             .selectAll('.selected')
53027             .classed('selected', false);
53028
53029         surface
53030             .selectAll('.related')
53031             .classed('related', false);
53032
53033         context.map().on('drawn.select', null);
53034         context.ui().sidebar.hide();
53035     };
53036
53037
53038     return mode;
53039 }
53040
53041 function uiAccount(context) {
53042     var connection = context.connection();
53043
53044
53045     function update(selection$$1) {
53046         if (!connection.authenticated()) {
53047             selection$$1.selectAll('#userLink, #logoutLink')
53048                 .classed('hide', true);
53049             return;
53050         }
53051
53052         connection.userDetails(function(err, details) {
53053             var userLink = selection$$1.select('#userLink'),
53054                 logoutLink = selection$$1.select('#logoutLink');
53055
53056             userLink.html('');
53057             logoutLink.html('');
53058
53059             if (err) return;
53060
53061             selection$$1.selectAll('#userLink, #logoutLink')
53062                 .classed('hide', false);
53063
53064             // Link
53065             userLink.append('a')
53066                 .attr('href', connection.userURL(details.display_name))
53067                 .attr('target', '_blank');
53068
53069             // Add thumbnail or dont
53070             if (details.image_url) {
53071                 userLink.append('img')
53072                     .attr('class', 'icon pre-text user-icon')
53073                     .attr('src', details.image_url);
53074             } else {
53075                 userLink
53076                     .call(svgIcon('#icon-avatar', 'pre-text light'));
53077             }
53078
53079             // Add user name
53080             userLink.append('span')
53081                 .attr('class', 'label')
53082                 .text(details.display_name);
53083
53084             logoutLink.append('a')
53085                 .attr('class', 'logout')
53086                 .attr('href', '#')
53087                 .text(t('logout'))
53088                 .on('click.logout', function() {
53089                     event.preventDefault();
53090                     connection.logout();
53091                 });
53092         });
53093     }
53094
53095
53096     return function(selection$$1) {
53097         selection$$1.append('li')
53098             .attr('id', 'logoutLink')
53099             .classed('hide', true);
53100
53101         selection$$1.append('li')
53102             .attr('id', 'userLink')
53103             .classed('hide', true);
53104
53105         connection
53106             .on('change.account', function() { update(selection$$1); });
53107
53108         update(selection$$1);
53109     };
53110 }
53111
53112 function uiAttribution(context) {
53113     var selection$$1;
53114
53115
53116     function attribution(data, klass) {
53117         var div = selection$$1.selectAll('.' + klass)
53118             .data([0]);
53119
53120         div = div.enter()
53121             .append('div')
53122             .attr('class', klass)
53123             .merge(div);
53124
53125
53126         var background = div.selectAll('.attribution')
53127             .data(data, function(d) { return d.name(); });
53128
53129         background.exit()
53130             .remove();
53131
53132         background = background.enter()
53133             .append('span')
53134             .attr('class', 'attribution')
53135             .each(function(d) {
53136                 if (d.terms_html) {
53137                     select(this)
53138                         .html(d.terms_html);
53139                     return;
53140                 }
53141
53142                 var source = d.terms_text || d.id || d.name();
53143
53144                 if (d.logo) {
53145                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
53146                 }
53147
53148                 if (d.terms_url) {
53149                     select(this)
53150                         .append('a')
53151                         .attr('href', d.terms_url)
53152                         .attr('target', '_blank')
53153                         .html(source);
53154                 } else {
53155                     select(this)
53156                         .text(source);
53157                 }
53158             })
53159             .merge(background);
53160
53161
53162         var copyright = background.selectAll('.copyright-notice')
53163             .data(function(d) {
53164                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
53165                 return notice ? [notice] : [];
53166             });
53167
53168         copyright.exit()
53169             .remove();
53170
53171         copyright = copyright.enter()
53172             .append('span')
53173             .attr('class', 'copyright-notice')
53174             .merge(copyright);
53175
53176         copyright
53177             .text(String);
53178     }
53179
53180
53181     function update() {
53182         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
53183         attribution(context.background().overlayLayerSources().filter(function (s) {
53184             return s.validZoom(context.map().zoom());
53185         }), 'overlay-layer-attribution');
53186     }
53187
53188
53189     return function(select$$1) {
53190         selection$$1 = select$$1;
53191
53192         context.background()
53193             .on('change.attribution', update);
53194
53195         context.map()
53196             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
53197
53198         update();
53199     };
53200 }
53201
53202 function rendererBackgroundSource(data) {
53203     var source = lodash.clone(data),
53204         offset = [0, 0],
53205         name = source.name,
53206         best = !!source.best;
53207
53208     source.scaleExtent = data.scaleExtent || [0, 20];
53209     source.overzoom = data.overzoom !== false;
53210
53211
53212     source.offset = function(_) {
53213         if (!arguments.length) return offset;
53214         offset = _;
53215         return source;
53216     };
53217
53218
53219     source.nudge = function(_, zoomlevel) {
53220         offset[0] += _[0] / Math.pow(2, zoomlevel);
53221         offset[1] += _[1] / Math.pow(2, zoomlevel);
53222         return source;
53223     };
53224
53225
53226     source.name = function() {
53227         return name;
53228     };
53229
53230
53231     source.best = function() {
53232         return best;
53233     };
53234
53235
53236     source.area = function() {
53237         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
53238         var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
53239         return isNaN(area$$1) ? 0 : area$$1;
53240     };
53241
53242
53243     source.imageryUsed = function() {
53244         return name || source.id;
53245     };
53246
53247
53248     source.url = function(coord) {
53249         return data.template
53250             .replace('{x}', coord[0])
53251             .replace('{y}', coord[1])
53252             // TMS-flipped y coordinate
53253             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
53254             .replace(/\{z(oom)?\}/, coord[2])
53255             .replace(/\{switch:([^}]+)\}/, function(s, r) {
53256                 var subdomains = r.split(',');
53257                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
53258             })
53259             .replace('{u}', function() {
53260                 var u = '';
53261                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
53262                     var b = 0;
53263                     var mask = 1 << (zoom$$1 - 1);
53264                     if ((coord[0] & mask) !== 0) b++;
53265                     if ((coord[1] & mask) !== 0) b += 2;
53266                     u += b.toString();
53267                 }
53268                 return u;
53269             });
53270     };
53271
53272
53273     source.intersects = function(extent$$1) {
53274         extent$$1 = extent$$1.polygon();
53275         return !data.polygon || data.polygon.some(function(polygon) {
53276             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
53277         });
53278     };
53279
53280
53281     source.validZoom = function(z) {
53282         return source.scaleExtent[0] <= z &&
53283             (source.overzoom || source.scaleExtent[1] > z);
53284     };
53285
53286
53287     source.isLocatorOverlay = function() {
53288         return source.id === 'mapbox_locator_overlay';
53289     };
53290
53291
53292     source.copyrightNotices = function() {};
53293
53294
53295     return source;
53296 }
53297
53298
53299 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
53300     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
53301     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
53302
53303     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
53304
53305     var bing = rendererBackgroundSource(data),
53306         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
53307         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
53308             key + '&jsonp={callback}',
53309         providers = [];
53310
53311     jsonpRequest(url, function(json$$1) {
53312         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
53313             return {
53314                 attribution: provider.attribution,
53315                 areas: provider.coverageAreas.map(function(area$$1) {
53316                     return {
53317                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
53318                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
53319                     };
53320                 })
53321             };
53322         });
53323         dispatch$$1.call('change');
53324     });
53325
53326     bing.copyrightNotices = function(zoom$$1, extent$$1) {
53327         zoom$$1 = Math.min(zoom$$1, 21);
53328         return providers.filter(function(provider) {
53329             return lodash.some(provider.areas, function(area$$1) {
53330                 return extent$$1.intersects(area$$1.extent) &&
53331                     area$$1.zoom[0] <= zoom$$1 &&
53332                     area$$1.zoom[1] >= zoom$$1;
53333             });
53334         }).map(function(provider) {
53335             return provider.attribution;
53336         }).join(', ');
53337     };
53338
53339     bing.logo = 'bing_maps.png';
53340     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
53341
53342     return bing;
53343 };
53344
53345
53346 rendererBackgroundSource.None = function() {
53347     var source = rendererBackgroundSource({ id: 'none', template: '' });
53348
53349     source.name = function() {
53350         return t('background.none');
53351     };
53352
53353     source.imageryUsed = function() {
53354         return 'None';
53355     };
53356
53357     source.area = function() {
53358         return -1;  // sources in background pane are sorted by area
53359     };
53360
53361     return source;
53362 };
53363
53364
53365 rendererBackgroundSource.Custom = function(template) {
53366     var source = rendererBackgroundSource({ id: 'custom', template: template });
53367
53368     source.name = function() {
53369         return t('background.custom');
53370     };
53371
53372     source.imageryUsed = function() {
53373         return 'Custom (' + template + ')';
53374     };
53375
53376     source.area = function() {
53377         return -2;  // sources in background pane are sorted by area
53378     };
53379
53380     return source;
53381 };
53382
53383 function rendererTileLayer(context) {
53384     var tileSize = 256,
53385         tile = d3geoTile(),
53386         projection,
53387         cache = {},
53388         tileOrigin,
53389         z,
53390         transformProp = utilPrefixCSSProperty('Transform'),
53391         source = rendererBackgroundSource.None();
53392
53393
53394     // blacklist overlay tiles around Null Island..
53395     function nearNullIsland(x, y, z) {
53396         if (z >= 7) {
53397             var center = Math.pow(2, z - 1),
53398                 width = Math.pow(2, z - 6),
53399                 min$$1 = center - (width / 2),
53400                 max$$1 = center + (width / 2) - 1;
53401             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
53402         }
53403         return false;
53404     }
53405
53406
53407     function tileSizeAtZoom(d, z) {
53408         var epsilon = 0.002;
53409         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
53410     }
53411
53412
53413     function atZoom(t, distance) {
53414         var power = Math.pow(2, distance);
53415         return [
53416             Math.floor(t[0] * power),
53417             Math.floor(t[1] * power),
53418             t[2] + distance];
53419     }
53420
53421
53422     function lookUp(d) {
53423         for (var up = -1; up > -d[2]; up--) {
53424             var tile = atZoom(d, up);
53425             if (cache[source.url(tile)] !== false) {
53426                 return tile;
53427             }
53428         }
53429     }
53430
53431
53432     function uniqueBy(a, n) {
53433         var o = [], seen = {};
53434         for (var i = 0; i < a.length; i++) {
53435             if (seen[a[i][n]] === undefined) {
53436                 o.push(a[i]);
53437                 seen[a[i][n]] = true;
53438             }
53439         }
53440         return o;
53441     }
53442
53443
53444     function addSource(d) {
53445         d.push(source.url(d));
53446         return d;
53447     }
53448
53449
53450     // Update tiles based on current state of `projection`.
53451     function background(selection$$1) {
53452         tile.scale(projection.scale() * 2 * Math.PI)
53453             .translate(projection.translate());
53454
53455         tileOrigin = [
53456             projection.scale() * Math.PI - projection.translate()[0],
53457             projection.scale() * Math.PI - projection.translate()[1]];
53458
53459         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
53460
53461         render(selection$$1);
53462     }
53463
53464
53465     // Derive the tiles onscreen, remove those offscreen and position them.
53466     // Important that this part not depend on `projection` because it's
53467     // rentered when tiles load/error (see #644).
53468     function render(selection$$1) {
53469         var requests = [];
53470         var showDebug = context.getDebug('tile') && !source.overlay;
53471
53472         if (source.validZoom(z)) {
53473             tile().forEach(function(d) {
53474                 addSource(d);
53475                 if (d[3] === '') return;
53476                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
53477                 requests.push(d);
53478                 if (cache[d[3]] === false && lookUp(d)) {
53479                     requests.push(addSource(lookUp(d)));
53480                 }
53481             });
53482
53483             requests = uniqueBy(requests, 3).filter(function(r) {
53484                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
53485                     return false;
53486                 }
53487                 // don't re-request tiles which have failed in the past
53488                 return cache[r[3]] !== false;
53489             });
53490         }
53491
53492         var pixelOffset = [
53493             source.offset()[0] * Math.pow(2, z),
53494             source.offset()[1] * Math.pow(2, z)
53495         ];
53496
53497         function load(d) {
53498             cache[d[3]] = true;
53499             select(this)
53500                 .on('error', null)
53501                 .on('load', null)
53502                 .classed('tile-loaded', true);
53503             render(selection$$1);
53504         }
53505
53506         function error(d) {
53507             cache[d[3]] = false;
53508             select(this)
53509                 .on('error', null)
53510                 .on('load', null)
53511                 .remove();
53512             render(selection$$1);
53513         }
53514
53515         function imageTransform(d) {
53516             var _ts = tileSize * Math.pow(2, z - d[2]);
53517             var scale = tileSizeAtZoom(d, z);
53518             return 'translate(' +
53519                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
53520                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
53521                 'scale(' + scale + ',' + scale + ')';
53522         }
53523
53524         function debugTransform(d) {
53525             var _ts = tileSize * Math.pow(2, z - d[2]);
53526             var scale = tileSizeAtZoom(d, z);
53527             return 'translate(' +
53528                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
53529                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
53530         }
53531
53532
53533         var image = selection$$1.selectAll('img')
53534             .data(requests, function(d) { return d[3]; });
53535
53536         image.exit()
53537             .style(transformProp, imageTransform)
53538             .classed('tile-removing', true)
53539             .each(function() {
53540                 var tile = select(this);
53541                 window.setTimeout(function() {
53542                     if (tile.classed('tile-removing')) {
53543                         tile.remove();
53544                     }
53545                 }, 300);
53546             });
53547
53548         image.enter()
53549           .append('img')
53550             .attr('class', 'tile')
53551             .attr('src', function(d) { return d[3]; })
53552             .on('error', error)
53553             .on('load', load)
53554           .merge(image)
53555             .style(transformProp, imageTransform)
53556             .classed('tile-debug', showDebug)
53557             .classed('tile-removing', false);
53558
53559
53560         var debug = selection$$1.selectAll('.tile-label-debug')
53561             .data(showDebug ? requests : [], function(d) { return d[3]; });
53562
53563         debug.exit()
53564             .remove();
53565
53566         debug.enter()
53567           .append('div')
53568             .attr('class', 'tile-label-debug')
53569           .merge(debug)
53570             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
53571             .style(transformProp, debugTransform);
53572     }
53573
53574
53575     background.projection = function(_) {
53576         if (!arguments.length) return projection;
53577         projection = _;
53578         return background;
53579     };
53580
53581
53582     background.dimensions = function(_) {
53583         if (!arguments.length) return tile.size();
53584         tile.size(_);
53585         return background;
53586     };
53587
53588
53589     background.source = function(_) {
53590         if (!arguments.length) return source;
53591         source = _;
53592         cache = {};
53593         tile.scaleExtent(source.scaleExtent);
53594         return background;
53595     };
53596
53597
53598     return background;
53599 }
53600
53601 function rendererBackground(context) {
53602     var dispatch$$1 = dispatch('change'),
53603         baseLayer = rendererTileLayer(context).projection(context.projection),
53604         overlayLayers = [],
53605         backgroundSources;
53606
53607
53608     function findSource(id) {
53609         return lodash.find(backgroundSources, function(d) {
53610             return d.id && d.id === id;
53611         });
53612     }
53613
53614
53615     function background(selection$$1) {
53616         var base = selection$$1.selectAll('.layer-background')
53617             .data([0]);
53618
53619         base.enter()
53620             .insert('div', '.layer-data')
53621             .attr('class', 'layer layer-background')
53622             .merge(base)
53623             .call(baseLayer);
53624
53625         var overlays = selection$$1.selectAll('.layer-overlay')
53626             .data(overlayLayers, function(d) { return d.source().name(); });
53627
53628         overlays.exit()
53629             .remove();
53630
53631         overlays.enter()
53632             .insert('div', '.layer-data')
53633             .attr('class', 'layer layer-overlay')
53634             .merge(overlays)
53635             .each(function(layer) { select(this).call(layer); });
53636     }
53637
53638
53639     background.updateImagery = function() {
53640         var b = background.baseLayerSource(),
53641             o = overlayLayers
53642                 .filter(function (d) { return !d.source().isLocatorOverlay(); })
53643                 .map(function (d) { return d.source().id; })
53644                 .join(','),
53645             meters = geoOffsetToMeters(b.offset()),
53646             epsilon = 0.01,
53647             x = +meters[0].toFixed(2),
53648             y = +meters[1].toFixed(2),
53649             q = utilStringQs(window.location.hash.substring(1));
53650
53651         var id = b.id;
53652         if (id === 'custom') {
53653             id = 'custom:' + b.template;
53654         }
53655
53656         if (id) {
53657             q.background = id;
53658         } else {
53659             delete q.background;
53660         }
53661
53662         if (o) {
53663             q.overlays = o;
53664         } else {
53665             delete q.overlays;
53666         }
53667
53668         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
53669             q.offset = x + ',' + y;
53670         } else {
53671             delete q.offset;
53672         }
53673
53674         window.location.replace('#' + utilQsString(q, true));
53675
53676         var imageryUsed = [b.imageryUsed()];
53677
53678         overlayLayers
53679             .filter(function (d) { return !d.source().isLocatorOverlay(); })
53680             .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
53681
53682         var gpx = context.layers().layer('gpx');
53683         if (gpx && gpx.enabled() && gpx.hasGpx()) {
53684             imageryUsed.push('Local GPX');
53685         }
53686
53687         var mapillary_images = context.layers().layer('mapillary-images');
53688         if (mapillary_images && mapillary_images.enabled()) {
53689             imageryUsed.push('Mapillary Images');
53690         }
53691
53692         var mapillary_signs = context.layers().layer('mapillary-signs');
53693         if (mapillary_signs && mapillary_signs.enabled()) {
53694             imageryUsed.push('Mapillary Signs');
53695         }
53696
53697         context.history().imageryUsed(imageryUsed);
53698     };
53699
53700
53701     background.sources = function(extent$$1) {
53702         return backgroundSources.filter(function(source) {
53703             return source.intersects(extent$$1);
53704         });
53705     };
53706
53707
53708     background.dimensions = function(_) {
53709         if (!_) return;
53710         baseLayer.dimensions(_);
53711
53712         overlayLayers.forEach(function(layer) {
53713             layer.dimensions(_);
53714         });
53715     };
53716
53717
53718     background.baseLayerSource = function(d) {
53719         if (!arguments.length) return baseLayer.source();
53720
53721         // test source against OSM imagery blacklists..
53722         var blacklists = context.connection().imageryBlacklists();
53723
53724         var fail = false,
53725             tested = 0,
53726             regex, i;
53727
53728         for (i = 0; i < blacklists; i++) {
53729             try {
53730                 regex = new RegExp(blacklists[i]);
53731                 fail = regex.test(d.template);
53732                 tested++;
53733                 if (fail) break;
53734             } catch (e) {
53735                 /* noop */
53736             }
53737         }
53738
53739         // ensure at least one test was run.
53740         if (!tested) {
53741             regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
53742             fail = regex.test(d.template);
53743         }
53744
53745         baseLayer.source(!fail ? d : rendererBackgroundSource.None());
53746         dispatch$$1.call('change');
53747         background.updateImagery();
53748         return background;
53749     };
53750
53751
53752     background.bing = function() {
53753         background.baseLayerSource(findSource('Bing'));
53754     };
53755
53756
53757     background.showsLayer = function(d) {
53758         return d.id === baseLayer.source().id ||
53759             overlayLayers.some(function(layer) { return d.id === layer.source().id; });
53760     };
53761
53762
53763     background.overlayLayerSources = function() {
53764         return overlayLayers.map(function (l) { return l.source(); });
53765     };
53766
53767
53768     background.toggleOverlayLayer = function(d) {
53769         var layer;
53770
53771         for (var i = 0; i < overlayLayers.length; i++) {
53772             layer = overlayLayers[i];
53773             if (layer.source() === d) {
53774                 overlayLayers.splice(i, 1);
53775                 dispatch$$1.call('change');
53776                 background.updateImagery();
53777                 return;
53778             }
53779         }
53780
53781         layer = rendererTileLayer(context)
53782             .source(d)
53783             .projection(context.projection)
53784             .dimensions(baseLayer.dimensions());
53785
53786         overlayLayers.push(layer);
53787         dispatch$$1.call('change');
53788         background.updateImagery();
53789     };
53790
53791
53792     background.nudge = function(d, zoom$$1) {
53793         baseLayer.source().nudge(d, zoom$$1);
53794         dispatch$$1.call('change');
53795         background.updateImagery();
53796         return background;
53797     };
53798
53799
53800     background.offset = function(d) {
53801         if (!arguments.length) return baseLayer.source().offset();
53802         baseLayer.source().offset(d);
53803         dispatch$$1.call('change');
53804         background.updateImagery();
53805         return background;
53806     };
53807
53808
53809     background.init = function() {
53810         function parseMap(qmap) {
53811             if (!qmap) return false;
53812             var args = qmap.split('/').map(Number);
53813             if (args.length < 3 || args.some(isNaN)) return false;
53814             return geoExtent$$1([args[2], args[1]]);
53815         }
53816
53817         var dataImagery = data.imagery || [],
53818             q = utilStringQs(window.location.hash.substring(1)),
53819             chosen = q.background || q.layer,
53820             extent$$1 = parseMap(q.map),
53821             best;
53822
53823         backgroundSources = dataImagery.map(function(source) {
53824             if (source.type === 'bing') {
53825                 return rendererBackgroundSource.Bing(source, dispatch$$1);
53826             } else {
53827                 return rendererBackgroundSource(source);
53828             }
53829         });
53830
53831         backgroundSources.unshift(rendererBackgroundSource.None());
53832
53833         if (!chosen && extent$$1) {
53834             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
53835         }
53836
53837         if (chosen && chosen.indexOf('custom:') === 0) {
53838             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
53839         } else {
53840             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
53841         }
53842
53843         var locator = lodash.find(backgroundSources, function(d) {
53844             return d.overlay && d.default;
53845         });
53846
53847         if (locator) {
53848             background.toggleOverlayLayer(locator);
53849         }
53850
53851         var overlays = (q.overlays || '').split(',');
53852         overlays.forEach(function(overlay) {
53853             overlay = findSource(overlay);
53854             if (overlay) {
53855                 background.toggleOverlayLayer(overlay);
53856             }
53857         });
53858
53859         if (q.gpx) {
53860             var gpx = context.layers().layer('gpx');
53861             if (gpx) {
53862                 gpx.url(q.gpx);
53863             }
53864         }
53865
53866         if (q.offset) {
53867             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
53868                 return !isNaN(n) && n;
53869             });
53870
53871             if (offset.length === 2) {
53872                 background.offset(geoMetersToOffset(offset));
53873             }
53874         }
53875     };
53876
53877
53878     return utilRebind(background, dispatch$$1, 'on');
53879 }
53880
53881 function rendererFeatures(context) {
53882     var traffic_roads = {
53883         'motorway': true,
53884         'motorway_link': true,
53885         'trunk': true,
53886         'trunk_link': true,
53887         'primary': true,
53888         'primary_link': true,
53889         'secondary': true,
53890         'secondary_link': true,
53891         'tertiary': true,
53892         'tertiary_link': true,
53893         'residential': true,
53894         'unclassified': true,
53895         'living_street': true
53896     };
53897
53898     var service_roads = {
53899         'service': true,
53900         'road': true,
53901         'track': true
53902     };
53903
53904     var paths = {
53905         'path': true,
53906         'footway': true,
53907         'cycleway': true,
53908         'bridleway': true,
53909         'steps': true,
53910         'pedestrian': true,
53911         'corridor': true
53912     };
53913
53914     var past_futures = {
53915         'proposed': true,
53916         'construction': true,
53917         'abandoned': true,
53918         'dismantled': true,
53919         'disused': true,
53920         'razed': true,
53921         'demolished': true,
53922         'obliterated': true
53923     };
53924
53925     var dispatch$$1 = dispatch('change', 'redraw'),
53926         _cullFactor = 1,
53927         _cache = {},
53928         _features = {},
53929         _stats = {},
53930         _keys = [],
53931         _hidden = [];
53932
53933
53934     function update() {
53935         _hidden = features.hidden();
53936         dispatch$$1.call('change');
53937         dispatch$$1.call('redraw');
53938     }
53939
53940
53941     function defineFeature(k, filter, max$$1) {
53942         _keys.push(k);
53943         _features[k] = {
53944             filter: filter,
53945             enabled: true,   // whether the user wants it enabled..
53946             count: 0,
53947             currentMax: (max$$1 || Infinity),
53948             defaultMax: (max$$1 || Infinity),
53949             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
53950             disable: function() { this.enabled = false; this.currentMax = 0; },
53951             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
53952             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
53953         };
53954     }
53955
53956
53957     defineFeature('points', function isPoint(entity, resolver, geometry) {
53958         return geometry === 'point';
53959     }, 200);
53960
53961     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53962         return traffic_roads[entity.tags.highway];
53963     });
53964
53965     defineFeature('service_roads', function isServiceRoad(entity) {
53966         return service_roads[entity.tags.highway];
53967     });
53968
53969     defineFeature('paths', function isPath(entity) {
53970         return paths[entity.tags.highway];
53971     });
53972
53973     defineFeature('buildings', function isBuilding(entity) {
53974         return (
53975             !!entity.tags['building:part'] ||
53976             (!!entity.tags.building && entity.tags.building !== 'no') ||
53977             entity.tags.amenity === 'shelter' ||
53978             entity.tags.parking === 'multi-storey' ||
53979             entity.tags.parking === 'sheds' ||
53980             entity.tags.parking === 'carports' ||
53981             entity.tags.parking === 'garage_boxes'
53982         );
53983     }, 250);
53984
53985     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
53986         return geometry === 'area' &&
53987             !_features.buildings.filter(entity) &&
53988             !_features.water.filter(entity);
53989     });
53990
53991     defineFeature('boundaries', function isBoundary(entity) {
53992         return !!entity.tags.boundary;
53993     });
53994
53995     defineFeature('water', function isWater(entity) {
53996         return (
53997             !!entity.tags.waterway ||
53998             entity.tags.natural === 'water' ||
53999             entity.tags.natural === 'coastline' ||
54000             entity.tags.natural === 'bay' ||
54001             entity.tags.landuse === 'pond' ||
54002             entity.tags.landuse === 'basin' ||
54003             entity.tags.landuse === 'reservoir' ||
54004             entity.tags.landuse === 'salt_pond'
54005         );
54006     });
54007
54008     defineFeature('rail', function isRail(entity) {
54009         return (
54010             !!entity.tags.railway ||
54011             entity.tags.landuse === 'railway'
54012         ) && !(
54013             traffic_roads[entity.tags.highway] ||
54014             service_roads[entity.tags.highway] ||
54015             paths[entity.tags.highway]
54016         );
54017     });
54018
54019     defineFeature('power', function isPower(entity) {
54020         return !!entity.tags.power;
54021     });
54022
54023     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
54024     defineFeature('past_future', function isPastFuture(entity) {
54025         if (
54026             traffic_roads[entity.tags.highway] ||
54027             service_roads[entity.tags.highway] ||
54028             paths[entity.tags.highway]
54029         ) { return false; }
54030
54031         var strings = Object.keys(entity.tags);
54032
54033         for (var i = 0; i < strings.length; i++) {
54034             var s = strings[i];
54035             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
54036         }
54037         return false;
54038     });
54039
54040     // Lines or areas that don't match another feature filter.
54041     // IMPORTANT: The 'others' feature must be the last one defined,
54042     //   so that code in getMatches can skip this test if `hasMatch = true`
54043     defineFeature('others', function isOther(entity, resolver, geometry) {
54044         return (geometry === 'line' || geometry === 'area');
54045     });
54046
54047
54048     function features() {}
54049
54050
54051     features.features = function() {
54052         return _features;
54053     };
54054
54055
54056     features.keys = function() {
54057         return _keys;
54058     };
54059
54060
54061     features.enabled = function(k) {
54062         if (!arguments.length) {
54063             return _keys.filter(function(k) { return _features[k].enabled; });
54064         }
54065         return _features[k] && _features[k].enabled;
54066     };
54067
54068
54069     features.disabled = function(k) {
54070         if (!arguments.length) {
54071             return _keys.filter(function(k) { return !_features[k].enabled; });
54072         }
54073         return _features[k] && !_features[k].enabled;
54074     };
54075
54076
54077     features.hidden = function(k) {
54078         if (!arguments.length) {
54079             return _keys.filter(function(k) { return _features[k].hidden(); });
54080         }
54081         return _features[k] && _features[k].hidden();
54082     };
54083
54084
54085     features.autoHidden = function(k) {
54086         if (!arguments.length) {
54087             return _keys.filter(function(k) { return _features[k].autoHidden(); });
54088         }
54089         return _features[k] && _features[k].autoHidden();
54090     };
54091
54092
54093     features.enable = function(k) {
54094         if (_features[k] && !_features[k].enabled) {
54095             _features[k].enable();
54096             update();
54097         }
54098     };
54099
54100
54101     features.disable = function(k) {
54102         if (_features[k] && _features[k].enabled) {
54103             _features[k].disable();
54104             update();
54105         }
54106     };
54107
54108
54109     features.toggle = function(k) {
54110         if (_features[k]) {
54111             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
54112             update();
54113         }
54114     };
54115
54116
54117     features.resetStats = function() {
54118         for (var i = 0; i < _keys.length; i++) {
54119             _features[_keys[i]].count = 0;
54120         }
54121         dispatch$$1.call('change');
54122     };
54123
54124
54125     features.gatherStats = function(d, resolver, dimensions) {
54126         var needsRedraw = false,
54127             type = lodash.groupBy(d, function(ent) { return ent.type; }),
54128             entities = [].concat(type.relation || [], type.way || [], type.node || []),
54129             currHidden, geometry, matches, i, j;
54130
54131         for (i = 0; i < _keys.length; i++) {
54132             _features[_keys[i]].count = 0;
54133         }
54134
54135         // adjust the threshold for point/building culling based on viewport size..
54136         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
54137         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
54138
54139         for (i = 0; i < entities.length; i++) {
54140             geometry = entities[i].geometry(resolver);
54141             if (!(geometry === 'vertex' || geometry === 'relation')) {
54142                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
54143                 for (j = 0; j < matches.length; j++) {
54144                     _features[matches[j]].count++;
54145                 }
54146             }
54147         }
54148
54149         currHidden = features.hidden();
54150         if (currHidden !== _hidden) {
54151             _hidden = currHidden;
54152             needsRedraw = true;
54153             dispatch$$1.call('change');
54154         }
54155
54156         return needsRedraw;
54157     };
54158
54159
54160     features.stats = function() {
54161         for (var i = 0; i < _keys.length; i++) {
54162             _stats[_keys[i]] = _features[_keys[i]].count;
54163         }
54164
54165         return _stats;
54166     };
54167
54168
54169     features.clear = function(d) {
54170         for (var i = 0; i < d.length; i++) {
54171             features.clearEntity(d[i]);
54172         }
54173     };
54174
54175
54176     features.clearEntity = function(entity) {
54177         delete _cache[osmEntity$$1.key(entity)];
54178     };
54179
54180
54181     features.reset = function() {
54182         _cache = {};
54183     };
54184
54185
54186     features.getMatches = function(entity, resolver, geometry) {
54187         if (geometry === 'vertex' || geometry === 'relation') return {};
54188
54189         var ent = osmEntity$$1.key(entity);
54190         if (!_cache[ent]) {
54191             _cache[ent] = {};
54192         }
54193
54194         if (!_cache[ent].matches) {
54195             var matches = {},
54196                 hasMatch = false;
54197
54198             for (var i = 0; i < _keys.length; i++) {
54199                 if (_keys[i] === 'others') {
54200                     if (hasMatch) continue;
54201
54202                     // Multipolygon members:
54203                     // If an entity...
54204                     //   1. is a way that hasn't matched other 'interesting' feature rules,
54205                     //   2. and it belongs to a single parent multipolygon relation
54206                     // ...then match whatever feature rules the parent multipolygon has matched.
54207                     // see #2548, #2887
54208                     //
54209                     // IMPORTANT:
54210                     // For this to work, getMatches must be called on relations before ways.
54211                     //
54212                     if (entity.type === 'way') {
54213                         var parents = features.getParents(entity, resolver, geometry);
54214                         if (parents.length === 1 && parents[0].isMultipolygon()) {
54215                             var pkey = osmEntity$$1.key(parents[0]);
54216                             if (_cache[pkey] && _cache[pkey].matches) {
54217                                 matches = lodash.clone(_cache[pkey].matches);
54218                                 continue;
54219                             }
54220                         }
54221                     }
54222                 }
54223
54224                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
54225                     matches[_keys[i]] = hasMatch = true;
54226                 }
54227             }
54228             _cache[ent].matches = matches;
54229         }
54230
54231         return _cache[ent].matches;
54232     };
54233
54234
54235     features.getParents = function(entity, resolver, geometry) {
54236         if (geometry === 'point') return [];
54237
54238         var ent = osmEntity$$1.key(entity);
54239         if (!_cache[ent]) {
54240             _cache[ent] = {};
54241         }
54242
54243         if (!_cache[ent].parents) {
54244             var parents = [];
54245             if (geometry === 'vertex') {
54246                 parents = resolver.parentWays(entity);
54247             } else {   // 'line', 'area', 'relation'
54248                 parents = resolver.parentRelations(entity);
54249             }
54250             _cache[ent].parents = parents;
54251         }
54252         return _cache[ent].parents;
54253     };
54254
54255
54256     features.isHiddenFeature = function(entity, resolver, geometry) {
54257         if (!_hidden.length) return false;
54258         if (!entity.version) return false;
54259
54260         var matches = features.getMatches(entity, resolver, geometry);
54261
54262         for (var i = 0; i < _hidden.length; i++) {
54263             if (matches[_hidden[i]]) return true;
54264         }
54265         return false;
54266     };
54267
54268
54269     features.isHiddenChild = function(entity, resolver, geometry) {
54270         if (!_hidden.length) return false;
54271         if (!entity.version || geometry === 'point') return false;
54272
54273         var parents = features.getParents(entity, resolver, geometry);
54274         if (!parents.length) return false;
54275
54276         for (var i = 0; i < parents.length; i++) {
54277             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
54278                 return false;
54279             }
54280         }
54281         return true;
54282     };
54283
54284
54285     features.hasHiddenConnections = function(entity, resolver) {
54286         if (!_hidden.length) return false;
54287         var childNodes, connections;
54288
54289         if (entity.type === 'midpoint') {
54290             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
54291             connections = [];
54292         } else {
54293             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
54294             connections = features.getParents(entity, resolver, entity.geometry(resolver));
54295         }
54296
54297         // gather ways connected to child nodes..
54298         connections = lodash.reduce(childNodes, function(result, e) {
54299             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
54300         }, connections);
54301
54302         return connections.length ? lodash.some(connections, function(e) {
54303             return features.isHidden(e, resolver, e.geometry(resolver));
54304         }) : false;
54305     };
54306
54307
54308     features.isHidden = function(entity, resolver, geometry) {
54309         if (!_hidden.length) return false;
54310         if (!entity.version) return false;
54311
54312         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
54313         return fn(entity, resolver, geometry);
54314     };
54315
54316
54317     features.filter = function(d, resolver) {
54318         if (!_hidden.length) return d;
54319
54320         var result = [];
54321         for (var i = 0; i < d.length; i++) {
54322             var entity = d[i];
54323             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
54324                 result.push(entity);
54325             }
54326         }
54327         return result;
54328     };
54329
54330
54331     return utilRebind(features, dispatch$$1, 'on');
54332 }
54333
54334 function utilBindOnce(target, type, listener, capture) {
54335     var typeOnce = type + '.once';
54336     function one() {
54337         target.on(typeOnce, null);
54338         listener.apply(this, arguments);
54339     }
54340     target.on(typeOnce, one, capture);
54341     return this;
54342 }
54343
54344 function rendererMap(context) {
54345
54346     var dimensions = [1, 1],
54347         dispatch$$1 = dispatch('move', 'drawn'),
54348         projection = context.projection,
54349         dblclickEnabled = true,
54350         redrawEnabled = true,
54351         transformStart = projection.transform(),
54352         transformed = false,
54353         minzoom = 0,
54354         drawLayers = svgLayers(projection, context),
54355         drawPoints = svgPoints$$1(projection, context),
54356         drawVertices = svgVertices$$1(projection, context),
54357         drawLines = svgLines$$1(projection),
54358         drawAreas = svgAreas$$1(projection, context),
54359         drawMidpoints = svgMidpoints$$1(projection, context),
54360         drawLabels = svgLabels(projection, context),
54361         supersurface = select(null),
54362         wrapper = select(null),
54363         surface = select(null),
54364         mouse$$1,
54365         mousemove;
54366
54367     var zoom$$1 = zoom$1()
54368             .scaleExtent([ztok(2), ztok(24)])
54369             .interpolate(value$1)
54370             .filter(zoomEventFilter)
54371             .on('zoom', zoomPan);
54372
54373     var _selection = select(null);
54374
54375
54376     function map$$1(selection$$1) {
54377
54378         _selection = selection$$1;
54379
54380         context
54381             .on('change.map', immediateRedraw);
54382
54383         context.connection()
54384             .on('change.map', immediateRedraw);
54385
54386         context.history()
54387             .on('change.map', immediateRedraw)
54388             .on('undone.context redone.context', function(stack$$1) {
54389                 var followSelected = false;
54390                 if (Array.isArray(stack$$1.selectedIDs)) {
54391                     followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
54392                     context.enter(
54393                         modeSelect(context, stack$$1.selectedIDs).suppressMenu(true).follow(followSelected)
54394                     );
54395                 }
54396                 if (!followSelected && stack$$1.transform) {
54397                     map$$1.transformEase(stack$$1.transform);
54398                 }
54399             });
54400
54401         context.background()
54402             .on('change.map', immediateRedraw);
54403
54404         context.features()
54405             .on('redraw.map', immediateRedraw);
54406
54407         drawLayers
54408             .on('change.map', function() {
54409                 context.background().updateImagery();
54410                 immediateRedraw();
54411             });
54412
54413         selection$$1
54414             .on('dblclick.map', dblClick)
54415             .call(zoom$$1)
54416             .call(zoom$$1.transform, projection.transform());
54417
54418         supersurface = selection$$1.append('div')
54419             .attr('id', 'supersurface')
54420             .call(utilSetTransform, 0, 0);
54421
54422         // Need a wrapper div because Opera can't cope with an absolutely positioned
54423         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
54424         wrapper = supersurface
54425             .append('div')
54426             .attr('class', 'layer layer-data');
54427
54428         map$$1.surface = surface = wrapper
54429             .call(drawLayers)
54430             .selectAll('.surface')
54431             .attr('id', 'surface');
54432
54433         surface
54434             .call(drawLabels.observe)
54435             .on('mousedown.zoom', function() {
54436                 if (event.button === 2) {
54437                     event.stopPropagation();
54438                 }
54439             }, true)
54440             .on('mouseup.zoom', function() {
54441                 if (resetTransform()) immediateRedraw();
54442             })
54443             .on('mousemove.map', function() {
54444                 mousemove = event;
54445             })
54446             .on('mouseover.vertices', function() {
54447                 if (map$$1.editable() && !transformed) {
54448                     var hover = event.target.__data__;
54449                     surface.selectAll('.data-layer-osm')
54450                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54451                     dispatch$$1.call('drawn', this, {full: false});
54452                 }
54453             })
54454             .on('mouseout.vertices', function() {
54455                 if (map$$1.editable() && !transformed) {
54456                     var hover = event.relatedTarget && event.relatedTarget.__data__;
54457                     surface.selectAll('.data-layer-osm')
54458                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54459                     dispatch$$1.call('drawn', this, {full: false});
54460                 }
54461             });
54462
54463         supersurface
54464             .call(context.background());
54465
54466         context.on('enter.map', function() {
54467             if (map$$1.editable() && !transformed) {
54468                 var all = context.intersects(map$$1.extent()),
54469                     filter = utilFunctor(true),
54470                     graph = context.graph();
54471
54472                 all = context.features().filter(all, graph);
54473                 surface.selectAll('.data-layer-osm')
54474                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
54475                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
54476                 dispatch$$1.call('drawn', this, {full: false});
54477             }
54478         });
54479
54480         map$$1.dimensions(utilGetDimensions(selection$$1));
54481     }
54482
54483
54484     function zoomEventFilter() {
54485         // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
54486         // Intercept `mousedown` and check if there is an orphaned zoom gesture.
54487         // This can happen if a previous `mousedown` occurred without a `mouseup`.
54488         // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
54489         // so that d3-zoom won't stop propagation of new `mousedown` events.
54490         if (event.type === 'mousedown') {
54491             var hasOrphan = false;
54492             var listeners = window.__on;
54493             for (var i = 0; i < listeners.length; i++) {
54494                 var listener = listeners[i];
54495                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
54496                     hasOrphan = true;
54497                     break;
54498                 }
54499             }
54500             if (hasOrphan) {
54501                 var event$$1 = window.CustomEvent;
54502                 if (event$$1) {
54503                     event$$1 = new event$$1('mouseup');
54504                 } else {
54505                     event$$1 = window.document.createEvent('Event');
54506                     event$$1.initEvent('mouseup', false, false);
54507                 }
54508                 // Event needs to be dispatched with an event.view property.
54509                 event$$1.view = window;
54510                 window.dispatchEvent(event$$1);
54511             }
54512         }
54513
54514         return event.button !== 2;   // ignore right clicks
54515     }
54516
54517
54518     function ztok(z) {
54519         return 256 * Math.pow(2, z);
54520     }
54521
54522     function ktoz(k) {
54523         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
54524     }
54525
54526     function pxCenter() {
54527         return [dimensions[0] / 2, dimensions[1] / 2];
54528     }
54529
54530
54531     function drawVector(difference, extent$$1) {
54532         var graph = context.graph(),
54533             features = context.features(),
54534             all = context.intersects(map$$1.extent()),
54535             data, filter;
54536
54537         if (difference) {
54538             var complete = difference.complete(map$$1.extent());
54539             data = lodash.compact(lodash.values(complete));
54540             filter = function(d) { return d.id in complete; };
54541             features.clear(data);
54542
54543         } else {
54544             // force a full redraw if gatherStats detects that a feature
54545             // should be auto-hidden (e.g. points or buildings)..
54546             if (features.gatherStats(all, graph, dimensions)) {
54547                 extent$$1 = undefined;
54548             }
54549
54550             if (extent$$1) {
54551                 data = context.intersects(map$$1.extent().intersection(extent$$1));
54552                 var set$$1 = set$2(lodash.map(data, 'id'));
54553                 filter = function(d) { return set$$1.has(d.id); };
54554
54555             } else {
54556                 data = all;
54557                 filter = utilFunctor(true);
54558             }
54559         }
54560
54561         data = features.filter(data, graph);
54562
54563         surface.selectAll('.data-layer-osm')
54564             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
54565             .call(drawLines, graph, data, filter)
54566             .call(drawAreas, graph, data, filter)
54567             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
54568             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
54569             .call(drawPoints, graph, data, filter);
54570
54571         dispatch$$1.call('drawn', this, {full: true});
54572     }
54573
54574
54575     function editOff() {
54576         context.features().resetStats();
54577         surface.selectAll('.layer-osm *').remove();
54578         dispatch$$1.call('drawn', this, {full: true});
54579     }
54580
54581
54582     function dblClick() {
54583         if (!dblclickEnabled) {
54584             event.preventDefault();
54585             event.stopImmediatePropagation();
54586         }
54587     }
54588
54589
54590     function zoomPan(manualEvent) {
54591         var eventTransform = (manualEvent || event).transform;
54592
54593         if (transformStart.x === eventTransform.x &&
54594             transformStart.y === eventTransform.y &&
54595             transformStart.k === eventTransform.k) {
54596             return;  // no change
54597         }
54598
54599         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
54600             surface.interrupt();
54601             uiFlash(context.container())
54602                 .select('.content')
54603                 .text(t('cannot_zoom'));
54604             setZoom(context.minEditableZoom(), true);
54605             queueRedraw();
54606             dispatch$$1.call('move', this, map$$1);
54607             return;
54608         }
54609
54610         projection.transform(eventTransform);
54611
54612         var scale = eventTransform.k / transformStart.k,
54613             tX = (eventTransform.x / scale - transformStart.x) * scale,
54614             tY = (eventTransform.y / scale - transformStart.y) * scale;
54615
54616         transformed = true;
54617         utilSetTransform(supersurface, tX, tY, scale);
54618         queueRedraw();
54619
54620         dispatch$$1.call('move', this, map$$1);
54621     }
54622
54623
54624     function resetTransform() {
54625         if (!transformed) return false;
54626
54627         surface.selectAll('.radial-menu').interrupt().remove();
54628         utilSetTransform(supersurface, 0, 0);
54629         transformed = false;
54630         return true;
54631     }
54632
54633
54634     function redraw(difference, extent$$1) {
54635         if (surface.empty() || !redrawEnabled) return;
54636
54637         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
54638         // It would result in artifacts where differenced entities are redrawn with
54639         // one transform and unchanged entities with another.
54640         if (resetTransform()) {
54641             difference = extent$$1 = undefined;
54642         }
54643
54644         var z = String(~~map$$1.zoom());
54645         if (surface.attr('data-zoom') !== z) {
54646             surface.attr('data-zoom', z)
54647                 .classed('low-zoom', z <= 16);
54648         }
54649
54650         if (!difference) {
54651             supersurface.call(context.background());
54652         }
54653
54654         wrapper
54655             .call(drawLayers);
54656
54657         // OSM
54658         if (map$$1.editable()) {
54659             context.loadTiles(projection, dimensions);
54660             drawVector(difference, extent$$1);
54661         } else {
54662             editOff();
54663         }
54664
54665         transformStart = projection.transform();
54666
54667         return map$$1;
54668     }
54669
54670
54671     var queueRedraw = lodash.throttle(redraw, 750);
54672
54673
54674     var immediateRedraw = function(difference, extent$$1) {
54675         if (!difference && !extent$$1) queueRedraw.cancel();
54676         redraw(difference, extent$$1);
54677     };
54678
54679
54680     function pointLocation(p) {
54681         var translate = projection.translate(),
54682             scale = projection.scale() * 2 * Math.PI;
54683         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
54684     }
54685
54686
54687     function locationPoint(l) {
54688         var translate = projection.translate(),
54689             scale = projection.scale() * 2 * Math.PI;
54690         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
54691     }
54692
54693
54694     map$$1.mouse = function() {
54695         var event$$1 = mousemove || event;
54696         if (event$$1) {
54697             var s;
54698             while ((s = event$$1.sourceEvent)) { event$$1 = s; }
54699             return mouse$$1(event$$1);
54700         }
54701         return null;
54702     };
54703
54704
54705     map$$1.mouseCoordinates = function() {
54706         return projection.invert(map$$1.mouse());
54707     };
54708
54709
54710     map$$1.dblclickEnable = function(_) {
54711         if (!arguments.length) return dblclickEnabled;
54712         dblclickEnabled = _;
54713         return map$$1;
54714     };
54715
54716
54717     map$$1.redrawEnable = function(_) {
54718         if (!arguments.length) return redrawEnabled;
54719         redrawEnabled = _;
54720         return map$$1;
54721     };
54722
54723
54724     function setTransform(t2, duration, force) {
54725         var t$$1 = projection.transform();
54726         if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
54727             return false;
54728         }
54729
54730         if (duration) {
54731             _selection
54732                 .transition()
54733                 .duration(duration)
54734                 .on('start', function() { map$$1.startEase(); })
54735                 .call(zoom$$1.transform, identity$9.translate(t2.x, t2.y).scale(t2.k));
54736         } else {
54737             projection.transform(t2);
54738             transformStart = t2;
54739             _selection.call(zoom$$1.transform, transformStart);
54740         }
54741     }
54742
54743
54744     function setZoom(z2, force, duration) {
54745         if (z2 === map$$1.zoom() && !force) {
54746             return false;
54747         }
54748
54749         var k = projection.scale(),
54750             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
54751             center = pxCenter(),
54752             l = pointLocation(center);
54753
54754         projection.scale(k2);
54755
54756         var t$$1 = projection.translate();
54757         l = locationPoint(l);
54758
54759         t$$1[0] += center[0] - l[0];
54760         t$$1[1] += center[1] - l[1];
54761
54762         if (duration) {
54763             projection.scale(k);  // reset scale
54764             _selection
54765                 .transition()
54766                 .duration(duration)
54767                 .on('start', function() { map$$1.startEase(); })
54768                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k2));
54769         } else {
54770             projection.translate(t$$1);
54771             transformStart = projection.transform();
54772             _selection.call(zoom$$1.transform, transformStart);
54773         }
54774
54775         return true;
54776     }
54777
54778
54779     function setCenter(loc2, duration) {
54780         var c = map$$1.center();
54781         if (loc2[0] === c[0] && loc2[1] === c[1]) {
54782             return false;
54783         }
54784
54785         var t$$1 = projection.translate(),
54786             k = projection.scale(),
54787             pxC = pxCenter(),
54788             ll = projection(loc2);
54789
54790         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
54791         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
54792
54793         if (duration) {
54794             _selection
54795                 .transition()
54796                 .duration(duration)
54797                 .on('start', function() { map$$1.startEase(); })
54798                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54799         } else {
54800             projection.translate(t$$1);
54801             transformStart = projection.transform();
54802             _selection.call(zoom$$1.transform, transformStart);
54803         }
54804
54805         return true;
54806     }
54807
54808
54809     map$$1.pan = function(delta, duration) {
54810         var t$$1 = projection.translate(),
54811             k = projection.scale();
54812
54813         t$$1[0] += delta[0];
54814         t$$1[1] += delta[1];
54815
54816         if (duration) {
54817             _selection
54818                 .transition()
54819                 .duration(duration)
54820                 .on('start', function() { map$$1.startEase(); })
54821                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54822         } else {
54823             projection.translate(t$$1);
54824             transformStart = projection.transform();
54825             _selection.call(zoom$$1.transform, transformStart);
54826             dispatch$$1.call('move', this, map$$1);
54827             immediateRedraw();
54828         }
54829
54830         return map$$1;
54831     };
54832
54833
54834     map$$1.dimensions = function(_) {
54835         if (!arguments.length) return dimensions;
54836         var center = map$$1.center();
54837         dimensions = _;
54838         drawLayers.dimensions(dimensions);
54839         context.background().dimensions(dimensions);
54840         projection.clipExtent([[0, 0], dimensions]);
54841         mouse$$1 = utilFastMouse(supersurface.node());
54842         setCenter(center);
54843
54844         queueRedraw();
54845         return map$$1;
54846     };
54847
54848
54849     function zoomIn(delta) {
54850         setZoom(~~map$$1.zoom() + delta, true, 250);
54851     }
54852
54853     function zoomOut(delta) {
54854         setZoom(~~map$$1.zoom() - delta, true, 250);
54855     }
54856
54857     map$$1.zoomIn = function() { zoomIn(1); };
54858     map$$1.zoomInFurther = function() { zoomIn(4); };
54859
54860     map$$1.zoomOut = function() { zoomOut(1); };
54861     map$$1.zoomOutFurther = function() { zoomOut(4); };
54862
54863
54864     map$$1.center = function(loc2) {
54865         if (!arguments.length) {
54866             return projection.invert(pxCenter());
54867         }
54868
54869         if (setCenter(loc2)) {
54870             dispatch$$1.call('move', this, map$$1);
54871         }
54872
54873         queueRedraw();
54874         return map$$1;
54875     };
54876
54877
54878     map$$1.zoom = function(z2) {
54879         if (!arguments.length) {
54880             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
54881         }
54882
54883         if (z2 < minzoom) {
54884             surface.interrupt();
54885             uiFlash(context.container())
54886                 .select('.content')
54887                 .text(t('cannot_zoom'));
54888             z2 = context.minEditableZoom();
54889         }
54890
54891         if (setZoom(z2)) {
54892             dispatch$$1.call('move', this, map$$1);
54893         }
54894
54895         queueRedraw();
54896         return map$$1;
54897     };
54898
54899
54900     map$$1.zoomTo = function(entity, zoomLimits) {
54901         var extent$$1 = entity.extent(context.graph());
54902         if (!isFinite(extent$$1.area())) return;
54903
54904         var z2 = map$$1.trimmedExtentZoom(extent$$1);
54905         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
54906         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
54907     };
54908
54909
54910     map$$1.centerZoom = function(loc2, z2) {
54911         var centered = setCenter(loc2),
54912             zoomed   = setZoom(z2);
54913
54914         if (centered || zoomed) {
54915             dispatch$$1.call('move', this, map$$1);
54916         }
54917
54918         queueRedraw();
54919         return map$$1;
54920     };
54921
54922
54923     map$$1.centerEase = function(loc2, duration) {
54924         duration = duration || 250;
54925         setCenter(loc2, duration);
54926         return map$$1;
54927     };
54928
54929
54930     map$$1.zoomEase = function(z2, duration) {
54931         duration = duration || 250;
54932         setZoom(z2, false, duration);
54933         return map$$1;
54934     };
54935
54936
54937     map$$1.transformEase = function(t2, duration) {
54938         duration = duration || 250;
54939         setTransform(t2, duration, false);
54940         return map$$1;
54941     };
54942
54943
54944     map$$1.startEase = function() {
54945         utilBindOnce(surface, 'mousedown.ease', function() {
54946             map$$1.cancelEase();
54947         });
54948         return map$$1;
54949     };
54950
54951
54952     map$$1.cancelEase = function() {
54953         _selection.interrupt();
54954         return map$$1;
54955     };
54956
54957
54958     map$$1.extent = function(_) {
54959         if (!arguments.length) {
54960             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
54961                                  projection.invert([dimensions[0], 0]));
54962         } else {
54963             var extent$$1 = geoExtent$$1(_);
54964             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
54965         }
54966     };
54967
54968
54969     map$$1.trimmedExtent = function(_) {
54970         if (!arguments.length) {
54971             var headerY = 60, footerY = 30, pad = 10;
54972             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
54973                                  projection.invert([dimensions[0] - pad, headerY + pad]));
54974         } else {
54975             var extent$$1 = geoExtent$$1(_);
54976             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
54977         }
54978     };
54979
54980
54981     function calcZoom(extent$$1, dim) {
54982         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
54983             br = projection([extent$$1[1][0], extent$$1[0][1]]);
54984
54985         // Calculate maximum zoom that fits extent
54986         var hFactor = (br[0] - tl[0]) / dim[0],
54987             vFactor = (br[1] - tl[1]) / dim[1],
54988             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
54989             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
54990             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
54991
54992         return newZoom;
54993     }
54994
54995
54996     map$$1.extentZoom = function(_) {
54997         return calcZoom(geoExtent$$1(_), dimensions);
54998     };
54999
55000
55001     map$$1.trimmedExtentZoom = function(_) {
55002         var trimY = 120, trimX = 40,
55003             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
55004         return calcZoom(geoExtent$$1(_), trimmed);
55005     };
55006
55007
55008     map$$1.editable = function() {
55009         return map$$1.zoom() >= context.minEditableZoom();
55010     };
55011
55012
55013     map$$1.minzoom = function(_) {
55014         if (!arguments.length) return minzoom;
55015         minzoom = _;
55016         return map$$1;
55017     };
55018
55019
55020     map$$1.layers = drawLayers;
55021
55022
55023     return utilRebind(map$$1, dispatch$$1, 'on');
55024 }
55025
55026 var TAU = 2 * Math.PI;
55027 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
55028 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
55029 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
55030 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
55031
55032
55033 function uiMapInMap(context) {
55034     var key = '/';
55035
55036
55037     function map_in_map(selection$$1) {
55038         var backgroundLayer = rendererTileLayer(context),
55039             overlayLayers = {},
55040             projection = geoRawMercator(),
55041             gpxLayer = svgGpx(projection, context).showLabels(false),
55042             debugLayer = svgDebug(projection, context),
55043             zoom$$1 = zoom$1()
55044                 .scaleExtent([ztok(0.5), ztok(24)])
55045                 .on('start', zoomStarted)
55046                 .on('zoom', zoomed)
55047                 .on('end', zoomEnded),
55048             isTransformed = false,
55049             isHidden = true,
55050             skipEvents = false,
55051             gesture = null,
55052             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
55053             wrap = select(null),
55054             tiles = select(null),
55055             viewport = select(null),
55056             tStart,  // transform at start of gesture
55057             tCurr,   // transform at most recent event
55058             timeoutId;
55059
55060
55061         function zoomStarted() {
55062             if (skipEvents) return;
55063             tStart = tCurr = projection.transform();
55064             gesture = null;
55065         }
55066
55067
55068         function zoomed() {
55069             if (skipEvents) return;
55070
55071             var x = event.transform.x,
55072                 y = event.transform.y,
55073                 k = event.transform.k,
55074                 isZooming = (k !== tStart.k),
55075                 isPanning = (x !== tStart.x || y !== tStart.y);
55076
55077             if (!isZooming && !isPanning) {
55078                 return;  // no change
55079             }
55080
55081             // lock in either zooming or panning, don't allow both in minimap.
55082             if (!gesture) {
55083                 gesture = isZooming ? 'zoom' : 'pan';
55084             }
55085
55086             var tMini = projection.transform(),
55087                 tX, tY, scale;
55088
55089             if (gesture === 'zoom') {
55090                 var dMini = utilGetDimensions(wrap),
55091                     cMini = vecScale(dMini, 0.5);
55092                 scale = k / tMini.k;
55093                 tX = (cMini[0] / scale - cMini[0]) * scale;
55094                 tY = (cMini[1] / scale - cMini[1]) * scale;
55095             } else {
55096                 k = tMini.k;
55097                 scale = 1;
55098                 tX = x - tMini.x;
55099                 tY = y - tMini.y;
55100             }
55101
55102             utilSetTransform(tiles, tX, tY, scale);
55103             utilSetTransform(viewport, 0, 0, scale);
55104             isTransformed = true;
55105             tCurr = identity$9.translate(x, y).scale(k);
55106
55107             var zMain = ktoz(context.projection.scale()),
55108                 zMini = ktoz(k);
55109
55110             zDiff = zMain - zMini;
55111
55112             queueRedraw();
55113         }
55114
55115
55116         function zoomEnded() {
55117             if (skipEvents) return;
55118             if (gesture !== 'pan') return;
55119
55120             updateProjection();
55121             gesture = null;
55122             var dMini = utilGetDimensions(wrap),
55123                 cMini = vecScale(dMini, 0.5);
55124             context.map().center(projection.invert(cMini));   // recenter main map..
55125         }
55126
55127
55128         function updateProjection() {
55129             var loc = context.map().center(),
55130                 dMini = utilGetDimensions(wrap),
55131                 cMini = vecScale(dMini, 0.5),
55132                 tMain = context.projection.transform(),
55133                 zMain = ktoz(tMain.k),
55134                 zMini = Math.max(zMain - zDiff, 0.5),
55135                 kMini = ztok(zMini);
55136
55137             projection
55138                 .translate([tMain.x, tMain.y])
55139                 .scale(kMini);
55140
55141             var point = projection(loc),
55142                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
55143                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
55144                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
55145
55146             projection
55147                 .translate([xMini, yMini])
55148                 .clipExtent([[0, 0], dMini]);
55149
55150             tCurr = projection.transform();
55151
55152             if (isTransformed) {
55153                 utilSetTransform(tiles, 0, 0);
55154                 utilSetTransform(viewport, 0, 0);
55155                 isTransformed = false;
55156             }
55157
55158             zoom$$1
55159                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
55160
55161             skipEvents = true;
55162             wrap.call(zoom$$1.transform, tCurr);
55163             skipEvents = false;
55164         }
55165
55166
55167         function redraw() {
55168             clearTimeout(timeoutId);
55169             if (isHidden) return;
55170
55171             updateProjection();
55172
55173             var dMini = utilGetDimensions(wrap),
55174                 zMini = ktoz(projection.scale());
55175
55176             // setup tile container
55177             tiles = wrap
55178                 .selectAll('.map-in-map-tiles')
55179                 .data([0]);
55180
55181             tiles = tiles.enter()
55182                 .append('div')
55183                 .attr('class', 'map-in-map-tiles')
55184                 .merge(tiles);
55185
55186             // redraw background
55187             backgroundLayer
55188                 .source(context.background().baseLayerSource())
55189                 .projection(projection)
55190                 .dimensions(dMini);
55191
55192             var background = tiles
55193                 .selectAll('.map-in-map-background')
55194                 .data([0]);
55195
55196             background.enter()
55197                 .append('div')
55198                 .attr('class', 'map-in-map-background')
55199                 .merge(background)
55200                 .call(backgroundLayer);
55201
55202
55203             // redraw overlay
55204             var overlaySources = context.background().overlayLayerSources();
55205             var activeOverlayLayers = [];
55206             for (var i = 0; i < overlaySources.length; i++) {
55207                 if (overlaySources[i].validZoom(zMini)) {
55208                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
55209                     activeOverlayLayers.push(overlayLayers[i]
55210                         .source(overlaySources[i])
55211                         .projection(projection)
55212                         .dimensions(dMini));
55213                 }
55214             }
55215
55216             var overlay = tiles
55217                 .selectAll('.map-in-map-overlay')
55218                 .data([0]);
55219
55220             overlay = overlay.enter()
55221                 .append('div')
55222                 .attr('class', 'map-in-map-overlay')
55223                 .merge(overlay);
55224
55225
55226             var overlays = overlay
55227                 .selectAll('div')
55228                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
55229
55230             overlays.exit()
55231                 .remove();
55232
55233             overlays = overlays.enter()
55234                 .append('div')
55235                 .merge(overlays)
55236                 .each(function(layer) { select(this).call(layer); });
55237
55238
55239             var dataLayers = tiles
55240                 .selectAll('.map-in-map-data')
55241                 .data([0]);
55242
55243             dataLayers.exit()
55244                 .remove();
55245
55246             dataLayers = dataLayers.enter()
55247                 .append('svg')
55248                 .attr('class', 'map-in-map-data')
55249                 .merge(dataLayers)
55250                 .call(gpxLayer)
55251                 .call(debugLayer);
55252
55253
55254             // redraw viewport bounding box
55255             if (gesture !== 'pan') {
55256                 var getPath = index$4(projection),
55257                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
55258
55259                 viewport = wrap.selectAll('.map-in-map-viewport')
55260                     .data([0]);
55261
55262                 viewport = viewport.enter()
55263                     .append('svg')
55264                     .attr('class', 'map-in-map-viewport')
55265                     .merge(viewport);
55266
55267
55268                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
55269                     .data([bbox]);
55270
55271                 path$$1.enter()
55272                     .append('path')
55273                     .attr('class', 'map-in-map-bbox')
55274                     .merge(path$$1)
55275                     .attr('d', getPath)
55276                     .classed('thick', function(d) { return getPath.area(d) < 30; });
55277             }
55278         }
55279
55280
55281         function queueRedraw() {
55282             clearTimeout(timeoutId);
55283             timeoutId = setTimeout(function() { redraw(); }, 750);
55284         }
55285
55286
55287         function toggle() {
55288             if (event) event.preventDefault();
55289
55290             isHidden = !isHidden;
55291
55292             var label = select('.minimap-toggle');
55293             label.classed('active', !isHidden)
55294                 .select('input').property('checked', !isHidden);
55295
55296             if (isHidden) {
55297                 wrap
55298                     .style('display', 'block')
55299                     .style('opacity', '1')
55300                     .transition()
55301                     .duration(200)
55302                     .style('opacity', '0')
55303                     .on('end', function() {
55304                         selection$$1.selectAll('.map-in-map')
55305                             .style('display', 'none');
55306                     });
55307             } else {
55308                 wrap
55309                     .style('display', 'block')
55310                     .style('opacity', '0')
55311                     .transition()
55312                     .duration(200)
55313                     .style('opacity', '1')
55314                     .on('end', function() {
55315                         redraw();
55316                     });
55317             }
55318         }
55319
55320
55321         uiMapInMap.toggle = toggle;
55322
55323         wrap = selection$$1.selectAll('.map-in-map')
55324             .data([0]);
55325
55326         wrap = wrap.enter()
55327             .append('div')
55328             .attr('class', 'map-in-map')
55329             .style('display', (isHidden ? 'none' : 'block'))
55330             .call(zoom$$1)
55331             .on('dblclick.zoom', null)
55332             .merge(wrap);
55333
55334         context.map()
55335             .on('drawn.map-in-map', function(drawn) {
55336                 if (drawn.full === true) {
55337                     redraw();
55338                 }
55339             });
55340
55341         redraw();
55342
55343         var keybinding = d3keybinding('map-in-map')
55344             .on(key, toggle);
55345
55346         select(document)
55347             .call(keybinding);
55348     }
55349
55350     return map_in_map;
55351 }
55352
55353 function uiTooltipHtml(text, key) {
55354     var s = '<span>' + text + '</span>';
55355     if (key) {
55356         s += '<div class="keyhint-wrap">' +
55357             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
55358             '<span class="keyhint"> ' + key + '</span></div>';
55359     }
55360     return s;
55361 }
55362
55363 function uiBackground(context) {
55364     var key = 'B',
55365         detected = utilDetect(),
55366         opacities = [1, 0.75, 0.5, 0.25],
55367         directions = [
55368             ['right', [0.5, 0]],
55369             ['top', [0, -0.5]],
55370             ['left', [-0.5, 0]],
55371             ['bottom', [0, 0.5]]],
55372         opacityDefault = (context.storage('background-opacity') !== null) ?
55373             (+context.storage('background-opacity')) : 1.0,
55374         customTemplate = context.storage('background-custom-template') || '',
55375         previous;
55376
55377     // Can be 0 from <1.3.0 use or due to issue #1923.
55378     if (opacityDefault === 0) opacityDefault = 1.0;
55379
55380
55381     function background(selection$$1) {
55382
55383         function sortSources(a, b) {
55384             return a.best() && !b.best() ? -1
55385                 : b.best() && !a.best() ? 1
55386                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
55387         }
55388
55389
55390         function setOpacity(d) {
55391             var bg = context.container().selectAll('.layer-background')
55392                 .transition()
55393                 .style('opacity', d)
55394                 .attr('data-opacity', d);
55395
55396             if (!detected.opera) {
55397                 utilSetTransform(bg, 0, 0);
55398             }
55399
55400             opacityList.selectAll('li')
55401                 .classed('active', function(_) { return _ === d; });
55402
55403             context.storage('background-opacity', d);
55404         }
55405
55406
55407         function setTooltips(selection$$1) {
55408             selection$$1.each(function(d, i, nodes) {
55409                 var item = select(this).select('label'),
55410                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
55411
55412                 if (d === previous) {
55413                     item.call(tooltip()
55414                         .placement(placement)
55415                         .html(true)
55416                         .title(function() {
55417                             var tip = '<div>' + t('background.switch') + '</div>';
55418                             return uiTooltipHtml(tip, uiCmd('⌘B'));
55419                         })
55420                     );
55421                 } else if (d.description) {
55422                     item.call(tooltip()
55423                         .placement(placement)
55424                         .title(d.description)
55425                     );
55426                 } else {
55427                     item.call(tooltip().destroy);
55428                 }
55429             });
55430         }
55431
55432
55433         function selectLayer() {
55434             function active$$1(d) {
55435                 return context.background().showsLayer(d);
55436             }
55437
55438             content.selectAll('.layer, .custom_layer')
55439                 .classed('active', active$$1)
55440                 .classed('switch', function(d) { return d === previous; })
55441                 .call(setTooltips)
55442                 .selectAll('input')
55443                 .property('checked', active$$1);
55444         }
55445
55446
55447         function clickSetSource(d) {
55448             event.preventDefault();
55449             previous = context.background().baseLayerSource();
55450             context.background().baseLayerSource(d);
55451             selectLayer();
55452             document.activeElement.blur();
55453         }
55454
55455
55456         function editCustom() {
55457             event.preventDefault();
55458             var template = window.prompt(t('background.custom_prompt'), customTemplate);
55459             if (template) {
55460                 setCustom(template);
55461             } else {
55462                 selectLayer();
55463             }
55464         }
55465
55466
55467         function setCustom(template) {
55468             context.storage('background-custom-template', template);
55469             var d = rendererBackgroundSource.Custom(template);
55470             content.selectAll('.custom_layer').datum(d);
55471             clickSetSource(d);
55472         }
55473
55474
55475         function clickSetOverlay(d) {
55476             event.preventDefault();
55477             context.background().toggleOverlayLayer(d);
55478             selectLayer();
55479             document.activeElement.blur();
55480         }
55481
55482
55483         function drawList(layerList, type, change, filter) {
55484             var sources = context.background()
55485                 .sources(context.map().extent())
55486                 .filter(filter);
55487
55488             var layerLinks = layerList.selectAll('li.layer')
55489                 .data(sources, function(d) { return d.name(); });
55490
55491             layerLinks.exit()
55492                 .remove();
55493
55494             var enter = layerLinks.enter()
55495                 .insert('li', '.custom_layer')
55496                 .attr('class', 'layer')
55497                 .classed('best', function(d) { return d.best(); });
55498
55499             enter.filter(function(d) { return d.best(); })
55500                 .append('div')
55501                 .attr('class', 'best')
55502                 .call(tooltip()
55503                     .title(t('background.best_imagery'))
55504                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
55505                 .append('span')
55506                 .html('&#9733;');
55507
55508             var label = enter
55509                 .append('label');
55510
55511             label
55512                 .append('input')
55513                 .attr('type', type)
55514                 .attr('name', 'layers')
55515                 .on('change', change);
55516
55517             label
55518                 .append('span')
55519                 .text(function(d) { return d.name(); });
55520
55521
55522             layerList.selectAll('li.layer')
55523                 .sort(sortSources)
55524                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
55525         }
55526
55527
55528         function update() {
55529             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
55530             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
55531
55532             selectLayer();
55533
55534             var source = context.background().baseLayerSource();
55535             if (source.id === 'custom') {
55536                 customTemplate = source.template;
55537             }
55538
55539             updateOffsetVal();
55540         }
55541
55542
55543         function updateOffsetVal() {
55544             var meters = geoOffsetToMeters(context.background().offset()),
55545                 x = +meters[0].toFixed(2),
55546                 y = +meters[1].toFixed(2);
55547
55548             selectAll('.nudge-inner-rect')
55549                 .select('input')
55550                 .classed('error', false)
55551                 .property('value', x + ', ' + y);
55552
55553             selectAll('.nudge-reset')
55554                 .classed('disabled', function() {
55555                     return (x === 0 && y === 0);
55556                 });
55557         }
55558
55559
55560         function resetOffset() {
55561             if (event.button !== 0) return;
55562             context.background().offset([0, 0]);
55563             updateOffsetVal();
55564         }
55565
55566
55567         function nudge(d) {
55568             context.background().nudge(d, context.map().zoom());
55569             updateOffsetVal();
55570         }
55571
55572
55573         function buttonOffset(d) {
55574             if (event.button !== 0) return;
55575             var timeout$$1 = window.setTimeout(function() {
55576                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
55577                 }, 500),
55578                 interval$$1;
55579
55580             function doneNudge() {
55581                 window.clearTimeout(timeout$$1);
55582                 window.clearInterval(interval$$1);
55583                 select(window)
55584                     .on('mouseup.buttonoffset', null, true)
55585                     .on('mousedown.buttonoffset', null, true);
55586             }
55587
55588             select(window)
55589                 .on('mouseup.buttonoffset', doneNudge, true)
55590                 .on('mousedown.buttonoffset', doneNudge, true);
55591
55592             nudge(d);
55593         }
55594
55595
55596         function inputOffset() {
55597             if (event.button !== 0) return;
55598             var input = select(this);
55599             var d = input.node().value;
55600
55601             if (d === '') return resetOffset();
55602
55603             d = d.replace(/;/g, ',').split(',').map(function(n) {
55604                 // if n is NaN, it will always get mapped to false.
55605                 return !isNaN(n) && n;
55606             });
55607
55608             if (d.length !== 2 || !d[0] || !d[1]) {
55609                 input.classed('error', true);
55610                 return;
55611             }
55612
55613             context.background().offset(geoMetersToOffset(d));
55614             updateOffsetVal();
55615         }
55616
55617
55618         function dragOffset() {
55619             if (event.button !== 0) return;
55620             var origin = [event.clientX, event.clientY];
55621
55622             context.container()
55623                 .append('div')
55624                 .attr('class', 'nudge-surface');
55625
55626             select(window)
55627                 .on('mousemove.offset', function() {
55628                     var latest = [event.clientX, event.clientY];
55629                     var d = [
55630                         -(origin[0] - latest[0]) / 4,
55631                         -(origin[1] - latest[1]) / 4
55632                     ];
55633
55634                     origin = latest;
55635                     nudge(d);
55636                 })
55637                 .on('mouseup.offset', function() {
55638                     if (event.button !== 0) return;
55639                     selectAll('.nudge-surface')
55640                         .remove();
55641
55642                     select(window)
55643                         .on('mousemove.offset', null)
55644                         .on('mouseup.offset', null);
55645                 });
55646
55647             event.preventDefault();
55648         }
55649
55650
55651         function hide() {
55652             setVisible(false);
55653         }
55654
55655
55656         function toggle() {
55657             if (event) event.preventDefault();
55658             tooltipBehavior.hide(button);
55659             setVisible(!button.classed('active'));
55660         }
55661
55662
55663         function quickSwitch() {
55664             if (previous) {
55665                 clickSetSource(previous);
55666             }
55667         }
55668
55669
55670         function setVisible(show) {
55671             if (show !== shown) {
55672                 button.classed('active', show);
55673                 shown = show;
55674
55675                 if (show) {
55676                     selection$$1.on('mousedown.background-inside', function() {
55677                         event.stopPropagation();
55678                     });
55679                     content
55680                         .style('display', 'block')
55681                         .style('right', '-300px')
55682                         .transition()
55683                         .duration(200)
55684                         .style('right', '0px');
55685                 } else {
55686                     content
55687                         .style('display', 'block')
55688                         .style('right', '0px')
55689                         .transition()
55690                         .duration(200)
55691                         .style('right', '-300px')
55692                         .on('end', function() {
55693                             select(this).style('display', 'none');
55694                         });
55695                     selection$$1.on('mousedown.background-inside', null);
55696                 }
55697             }
55698         }
55699
55700
55701         var content = selection$$1
55702                 .append('div')
55703                 .attr('class', 'fillL map-overlay col3 content hide'),
55704             tooltipBehavior = tooltip()
55705                 .placement((textDirection === 'rtl') ? 'right' : 'left')
55706                 .html(true)
55707                 .title(uiTooltipHtml(t('background.description'), key)),
55708             button = selection$$1
55709                 .append('button')
55710                 .attr('tabindex', -1)
55711                 .on('click', toggle)
55712                 .call(svgIcon('#icon-layers', 'light'))
55713                 .call(tooltipBehavior),
55714             shown = false;
55715
55716
55717         /* opacity switcher */
55718
55719         var opawrap = content
55720                 .append('div')
55721                 .attr('class', 'opacity-options-wrapper');
55722
55723         opawrap
55724             .append('h4')
55725             .text(t('background.title'));
55726
55727         var opacityList = opawrap
55728             .append('ul')
55729             .attr('class', 'opacity-options');
55730
55731         opacityList.selectAll('div.opacity')
55732             .data(opacities)
55733             .enter()
55734             .append('li')
55735             .attr('data-original-title', function(d) {
55736                 return t('background.percent_brightness', { opacity: (d * 100) });
55737             })
55738             .on('click.set-opacity', setOpacity)
55739             .html('<div class="select-box"></div>')
55740             .call(tooltip()
55741                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55742             .append('div')
55743             .attr('class', 'opacity')
55744             .style('opacity', function(d) { return 1.25 - d; });
55745
55746
55747         /* background switcher */
55748
55749         var backgroundList = content
55750             .append('ul')
55751             .attr('class', 'layer-list')
55752             .attr('dir', 'auto');
55753
55754         var custom = backgroundList
55755             .append('li')
55756             .attr('class', 'custom_layer')
55757             .datum(rendererBackgroundSource.Custom());
55758
55759         custom
55760             .append('button')
55761             .attr('class', 'layer-browse')
55762             .call(tooltip()
55763                 .title(t('background.custom_button'))
55764                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55765             .on('click', editCustom)
55766             .call(svgIcon('#icon-search'));
55767
55768         var label = custom
55769             .append('label');
55770
55771         label
55772             .append('input')
55773             .attr('type', 'radio')
55774             .attr('name', 'layers')
55775             .on('change', function () {
55776                 if (customTemplate) {
55777                     setCustom(customTemplate);
55778                 } else {
55779                     editCustom();
55780                 }
55781             });
55782
55783         label
55784             .append('span')
55785             .text(t('background.custom'));
55786
55787         content
55788             .append('div')
55789             .attr('class', 'imagery-faq')
55790             .append('a')
55791             .attr('target', '_blank')
55792             .attr('tabindex', -1)
55793             .call(svgIcon('#icon-out-link', 'inline'))
55794             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
55795             .append('span')
55796             .text(t('background.imagery_source_faq'));
55797
55798         var overlayList = content
55799             .append('ul')
55800             .attr('class', 'layer-list');
55801
55802         var controls = content
55803             .append('div')
55804             .attr('class', 'controls-list');
55805
55806
55807         /* minimap toggle */
55808
55809         var minimapLabel = controls
55810             .append('label')
55811             .call(tooltip()
55812                 .html(true)
55813                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
55814                 .placement('top')
55815             );
55816
55817         minimapLabel
55818             .classed('minimap-toggle', true)
55819             .append('input')
55820             .attr('type', 'checkbox')
55821             .on('change', function() {
55822                 uiMapInMap.toggle();
55823                 event.preventDefault();
55824             });
55825
55826         minimapLabel
55827             .append('span')
55828             .text(t('background.minimap.description'));
55829
55830
55831         /* imagery offset controls */
55832
55833         var adjustments = content
55834             .append('div')
55835             .attr('class', 'adjustments');
55836
55837         adjustments
55838             .append('a')
55839             .text(t('background.fix_misalignment'))
55840             .attr('href', '#')
55841             .classed('hide-toggle', true)
55842             .classed('expanded', false)
55843             .on('click', function() {
55844                 if (event.button !== 0) return;
55845                 var exp = select(this).classed('expanded');
55846                 nudgeContainer.style('display', exp ? 'none' : 'block');
55847                 select(this).classed('expanded', !exp);
55848                 event.preventDefault();
55849             });
55850
55851         var nudgeContainer = adjustments
55852             .append('div')
55853             .attr('class', 'nudge-container cf')
55854             .style('display', 'none');
55855
55856         nudgeContainer
55857             .append('div')
55858             .attr('class', 'nudge-instructions')
55859             .text(t('background.offset'));
55860
55861         var nudgeRect = nudgeContainer
55862             .append('div')
55863             .attr('class', 'nudge-outer-rect')
55864             .on('mousedown', dragOffset);
55865
55866         nudgeRect
55867             .append('div')
55868             .attr('class', 'nudge-inner-rect')
55869             .append('input')
55870             .on('change', inputOffset)
55871             .on('mousedown', function() {
55872                 if (event.button !== 0) return;
55873                 event.stopPropagation();
55874             });
55875
55876         nudgeContainer
55877             .append('div')
55878             .selectAll('button')
55879             .data(directions).enter()
55880             .append('button')
55881             .attr('class', function(d) { return d[0] + ' nudge'; })
55882             .on('mousedown', function(d) {
55883                 if (event.button !== 0) return;
55884                 buttonOffset(d[1]);
55885             });
55886
55887         nudgeContainer
55888             .append('button')
55889             .attr('title', t('background.reset'))
55890             .attr('class', 'nudge-reset disabled')
55891             .on('click', resetOffset)
55892             .call(
55893                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
55894             );
55895
55896         context.map()
55897             .on('move.background-update', lodash.debounce(update, 1000));
55898
55899         context.background()
55900             .on('change.background-update', update);
55901
55902
55903         update();
55904         setOpacity(opacityDefault);
55905
55906         var keybinding = d3keybinding('background')
55907             .on(key, toggle)
55908             .on(uiCmd('⌘B'), quickSwitch)
55909             .on('F', hide)
55910             .on('H', hide);
55911
55912         select(document)
55913             .call(keybinding);
55914
55915         context.surface().on('mousedown.background-outside', hide);
55916         context.container().on('mousedown.background-outside', hide);
55917     }
55918
55919     return background;
55920 }
55921
55922 function uiContributors(context) {
55923     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
55924         limit = 4,
55925         hidden = false,
55926         wrap = select(null);
55927
55928
55929     function update() {
55930         var users = {},
55931             entities = context.intersects(context.map().extent());
55932
55933         entities.forEach(function(entity) {
55934             if (entity && entity.user) users[entity.user] = true;
55935         });
55936
55937         var u = Object.keys(users),
55938             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
55939
55940         wrap.html('')
55941             .call(svgIcon('#icon-nearby', 'pre-text light'));
55942
55943         var userList = select(document.createElement('span'));
55944
55945         userList.selectAll()
55946             .data(subset)
55947             .enter()
55948             .append('a')
55949             .attr('class', 'user-link')
55950             .attr('href', function(d) { return context.connection().userURL(d); })
55951             .attr('target', '_blank')
55952             .attr('tabindex', -1)
55953             .text(String);
55954
55955         if (u.length > limit) {
55956             var count = select(document.createElement('span'));
55957
55958             count.append('a')
55959                 .attr('target', '_blank')
55960                 .attr('tabindex', -1)
55961                 .attr('href', function() {
55962                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
55963                 })
55964                 .text(u.length - limit + 1);
55965
55966             wrap.append('span')
55967                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
55968
55969         } else {
55970             wrap.append('span')
55971                 .html(t('contributors.list', { users: userList.html() }));
55972         }
55973
55974         if (!u.length) {
55975             hidden = true;
55976             wrap
55977                 .transition()
55978                 .style('opacity', 0);
55979
55980         } else if (hidden) {
55981             wrap
55982                 .transition()
55983                 .style('opacity', 1);
55984         }
55985     }
55986
55987
55988     return function(selection$$1) {
55989         wrap = selection$$1;
55990         update();
55991
55992         context.connection().on('loaded.contributors', debouncedUpdate);
55993         context.map().on('move.contributors', debouncedUpdate);
55994     };
55995 }
55996
55997 function uiFeatureInfo(context) {
55998     function update(selection$$1) {
55999         var features = context.features(),
56000             stats = features.stats(),
56001             count = 0,
56002             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
56003                 if (stats[k]) {
56004                     count += stats[k];
56005                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
56006                 }
56007             }));
56008
56009         selection$$1.html('');
56010
56011         if (hiddenList.length) {
56012             var tooltipBehavior = tooltip()
56013                     .placement('top')
56014                     .html(true)
56015                     .title(function() {
56016                         return uiTooltipHtml(hiddenList.join('<br/>'));
56017                     });
56018
56019             var warning = selection$$1.append('a')
56020                 .attr('href', '#')
56021                 .attr('tabindex', -1)
56022                 .html(t('feature_info.hidden_warning', { count: count }))
56023                 .call(tooltipBehavior)
56024                 .on('click', function() {
56025                     tooltipBehavior.hide(warning);
56026                     // open map data panel?
56027                     event.preventDefault();
56028                 });
56029         }
56030
56031         selection$$1
56032             .classed('hide', !hiddenList.length);
56033     }
56034
56035
56036     return function(selection$$1) {
56037         update(selection$$1);
56038
56039         context.features().on('change.feature_info', function() {
56040             update(selection$$1);
56041         });
56042     };
56043 }
56044
56045 function uiFullScreen(context) {
56046     var element = context.container().node(),
56047         keybinding = d3keybinding('full-screen');
56048         // button;
56049
56050
56051     function getFullScreenFn() {
56052         if (element.requestFullscreen) {
56053             return element.requestFullscreen;
56054         } else if (element.msRequestFullscreen) {
56055             return element.msRequestFullscreen;
56056         } else if (element.mozRequestFullScreen) {
56057             return element.mozRequestFullScreen;
56058         } else if (element.webkitRequestFullscreen) {
56059             return element.webkitRequestFullscreen;
56060         }
56061     }
56062
56063
56064     function getExitFullScreenFn() {
56065         if (document.exitFullscreen) {
56066             return document.exitFullscreen;
56067         } else if (document.msExitFullscreen) {
56068             return document.msExitFullscreen;
56069         } else if (document.mozCancelFullScreen) {
56070             return document.mozCancelFullScreen;
56071         } else if (document.webkitExitFullscreen) {
56072             return document.webkitExitFullscreen;
56073         }
56074     }
56075
56076
56077     function isFullScreen() {
56078         return document.fullscreenElement ||
56079             document.mozFullScreenElement ||
56080             document.webkitFullscreenElement ||
56081             document.msFullscreenElement;
56082     }
56083
56084
56085     function isSupported() {
56086         return !!getFullScreenFn();
56087     }
56088
56089
56090     function fullScreen() {
56091         event.preventDefault();
56092         if (!isFullScreen()) {
56093             // button.classed('active', true);
56094             getFullScreenFn().apply(element);
56095         } else {
56096             // button.classed('active', false);
56097             getExitFullScreenFn().apply(document);
56098         }
56099     }
56100
56101
56102     return function() { // selection) {
56103         if (!isSupported())
56104             return;
56105
56106         // button = selection.append('button')
56107         //     .attr('title', t('full_screen'))
56108         //     .attr('tabindex', -1)
56109         //     .on('click', fullScreen)
56110         //     .call(tooltip);
56111
56112         // button.append('span')
56113         //     .attr('class', 'icon full-screen');
56114
56115         keybinding
56116             .on('f11', fullScreen)
56117             .on(uiCmd('⌘⇧F'), fullScreen);
56118
56119         select(document)
56120             .call(keybinding);
56121     };
56122 }
56123
56124 function uiModal(selection$$1, blocking) {
56125     var keybinding = d3keybinding('modal');
56126     var previous = selection$$1.select('div.modal');
56127     var animate = previous.empty();
56128
56129     previous.transition()
56130         .duration(200)
56131         .style('opacity', 0)
56132         .remove();
56133
56134     var shaded = selection$$1
56135         .append('div')
56136         .attr('class', 'shaded')
56137         .style('opacity', 0);
56138
56139     shaded.close = function() {
56140         shaded
56141             .transition()
56142             .duration(200)
56143             .style('opacity',0)
56144             .remove();
56145
56146         modal
56147             .transition()
56148             .duration(200)
56149             .style('top','0px');
56150
56151         keybinding.off();
56152     };
56153
56154
56155     var modal = shaded
56156         .append('div')
56157         .attr('class', 'modal fillL col6');
56158
56159     if (!blocking) {
56160         shaded.on('click.remove-modal', function() {
56161             if (event.target === this) {
56162                 shaded.close();
56163             }
56164         });
56165
56166         modal.append('button')
56167             .attr('class', 'close')
56168             .on('click', shaded.close)
56169             .call(svgIcon('#icon-close'));
56170
56171         keybinding
56172             .on('⌫', shaded.close)
56173             .on('⎋', shaded.close);
56174
56175         select(document)
56176             .call(keybinding);
56177     }
56178
56179     modal
56180         .append('div')
56181         .attr('class', 'content');
56182
56183     if (animate) {
56184         shaded.transition().style('opacity', 1);
56185     } else {
56186         shaded.style('opacity', 1);
56187     }
56188
56189
56190     return shaded;
56191 }
56192
56193 function uiLoading(context) {
56194     var message = '',
56195         blocking = false,
56196         modalSelection;
56197
56198
56199     var loading = function(selection) {
56200         modalSelection = uiModal(selection, blocking);
56201
56202         var loadertext = modalSelection.select('.content')
56203             .classed('loading-modal', true)
56204             .append('div')
56205             .attr('class', 'modal-section fillL');
56206
56207         loadertext
56208             .append('img')
56209             .attr('class', 'loader')
56210             .attr('src', context.imagePath('loader-white.gif'));
56211
56212         loadertext
56213             .append('h3')
56214             .text(message);
56215
56216         modalSelection.select('button.close')
56217             .attr('class', 'hide');
56218
56219         return loading;
56220     };
56221
56222
56223     loading.message = function(_) {
56224         if (!arguments.length) return message;
56225         message = _;
56226         return loading;
56227     };
56228
56229
56230     loading.blocking = function(_) {
56231         if (!arguments.length) return blocking;
56232         blocking = _;
56233         return loading;
56234     };
56235
56236
56237     loading.close = function() {
56238         modalSelection.remove();
56239     };
56240
56241
56242     return loading;
56243 }
56244
56245 function uiGeolocate(context) {
56246     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
56247         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
56248         timeoutId;
56249
56250
56251     function click() {
56252         context.enter(modeBrowse(context));
56253         context.container().call(locating);
56254         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
56255
56256         // This timeout ensures that we still call finish() even if
56257         // the user declines to share their location in Firefox
56258         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
56259     }
56260
56261
56262     function success(position) {
56263         var map = context.map(),
56264             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
56265                 .padByMeters(position.coords.accuracy);
56266
56267         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
56268         finish();
56269     }
56270
56271
56272     function error() {
56273         finish();
56274     }
56275
56276
56277     function finish() {
56278         locating.close();  // unblock ui
56279         if (timeoutId) { clearTimeout(timeoutId); }
56280         timeoutId = undefined;
56281     }
56282
56283
56284     return function(selection) {
56285         if (!navigator.geolocation) return;
56286
56287         selection
56288             .append('button')
56289             .attr('tabindex', -1)
56290             .attr('title', t('geolocate.title'))
56291             .on('click', click)
56292             .call(svgIcon('#icon-geolocate', 'light'))
56293             .call(tooltip()
56294                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
56295     };
56296 }
56297
56298 var marked = createCommonjsModule(function (module, exports) {
56299 /**
56300  * marked - a markdown parser
56301  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
56302  * https://github.com/chjj/marked
56303  */
56304
56305 (function() {
56306
56307 /**
56308  * Block-Level Grammar
56309  */
56310
56311 var block = {
56312   newline: /^\n+/,
56313   code: /^( {4}[^\n]+\n*)+/,
56314   fences: noop,
56315   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
56316   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
56317   nptable: noop,
56318   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
56319   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
56320   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
56321   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
56322   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
56323   table: noop,
56324   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
56325   text: /^[^\n]+/
56326 };
56327
56328 block.bullet = /(?:[*+-]|\d+\.)/;
56329 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
56330 block.item = replace(block.item, 'gm')
56331   (/bull/g, block.bullet)
56332   ();
56333
56334 block.list = replace(block.list)
56335   (/bull/g, block.bullet)
56336   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
56337   ('def', '\\n+(?=' + block.def.source + ')')
56338   ();
56339
56340 block.blockquote = replace(block.blockquote)
56341   ('def', block.def)
56342   ();
56343
56344 block._tag = '(?!(?:'
56345   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
56346   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
56347   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
56348
56349 block.html = replace(block.html)
56350   ('comment', /<!--[\s\S]*?-->/)
56351   ('closed', /<(tag)[\s\S]+?<\/\1>/)
56352   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
56353   (/tag/g, block._tag)
56354   ();
56355
56356 block.paragraph = replace(block.paragraph)
56357   ('hr', block.hr)
56358   ('heading', block.heading)
56359   ('lheading', block.lheading)
56360   ('blockquote', block.blockquote)
56361   ('tag', '<' + block._tag)
56362   ('def', block.def)
56363   ();
56364
56365 /**
56366  * Normal Block Grammar
56367  */
56368
56369 block.normal = merge({}, block);
56370
56371 /**
56372  * GFM Block Grammar
56373  */
56374
56375 block.gfm = merge({}, block.normal, {
56376   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
56377   paragraph: /^/,
56378   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
56379 });
56380
56381 block.gfm.paragraph = replace(block.paragraph)
56382   ('(?!', '(?!'
56383     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
56384     + block.list.source.replace('\\1', '\\3') + '|')
56385   ();
56386
56387 /**
56388  * GFM + Tables Block Grammar
56389  */
56390
56391 block.tables = merge({}, block.gfm, {
56392   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
56393   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
56394 });
56395
56396 /**
56397  * Block Lexer
56398  */
56399
56400 function Lexer(options) {
56401   this.tokens = [];
56402   this.tokens.links = {};
56403   this.options = options || marked.defaults;
56404   this.rules = block.normal;
56405
56406   if (this.options.gfm) {
56407     if (this.options.tables) {
56408       this.rules = block.tables;
56409     } else {
56410       this.rules = block.gfm;
56411     }
56412   }
56413 }
56414
56415 /**
56416  * Expose Block Rules
56417  */
56418
56419 Lexer.rules = block;
56420
56421 /**
56422  * Static Lex Method
56423  */
56424
56425 Lexer.lex = function(src, options) {
56426   var lexer = new Lexer(options);
56427   return lexer.lex(src);
56428 };
56429
56430 /**
56431  * Preprocessing
56432  */
56433
56434 Lexer.prototype.lex = function(src) {
56435   src = src
56436     .replace(/\r\n|\r/g, '\n')
56437     .replace(/\t/g, '    ')
56438     .replace(/\u00a0/g, ' ')
56439     .replace(/\u2424/g, '\n');
56440
56441   return this.token(src, true);
56442 };
56443
56444 /**
56445  * Lexing
56446  */
56447
56448 Lexer.prototype.token = function(src, top, bq) {
56449   var src = src.replace(/^ +$/gm, '')
56450     , next
56451     , loose
56452     , cap
56453     , bull
56454     , b
56455     , item
56456     , space
56457     , i
56458     , l;
56459
56460   while (src) {
56461     // newline
56462     if (cap = this.rules.newline.exec(src)) {
56463       src = src.substring(cap[0].length);
56464       if (cap[0].length > 1) {
56465         this.tokens.push({
56466           type: 'space'
56467         });
56468       }
56469     }
56470
56471     // code
56472     if (cap = this.rules.code.exec(src)) {
56473       src = src.substring(cap[0].length);
56474       cap = cap[0].replace(/^ {4}/gm, '');
56475       this.tokens.push({
56476         type: 'code',
56477         text: !this.options.pedantic
56478           ? cap.replace(/\n+$/, '')
56479           : cap
56480       });
56481       continue;
56482     }
56483
56484     // fences (gfm)
56485     if (cap = this.rules.fences.exec(src)) {
56486       src = src.substring(cap[0].length);
56487       this.tokens.push({
56488         type: 'code',
56489         lang: cap[2],
56490         text: cap[3] || ''
56491       });
56492       continue;
56493     }
56494
56495     // heading
56496     if (cap = this.rules.heading.exec(src)) {
56497       src = src.substring(cap[0].length);
56498       this.tokens.push({
56499         type: 'heading',
56500         depth: cap[1].length,
56501         text: cap[2]
56502       });
56503       continue;
56504     }
56505
56506     // table no leading pipe (gfm)
56507     if (top && (cap = this.rules.nptable.exec(src))) {
56508       src = src.substring(cap[0].length);
56509
56510       item = {
56511         type: 'table',
56512         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56513         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56514         cells: cap[3].replace(/\n$/, '').split('\n')
56515       };
56516
56517       for (i = 0; i < item.align.length; i++) {
56518         if (/^ *-+: *$/.test(item.align[i])) {
56519           item.align[i] = 'right';
56520         } else if (/^ *:-+: *$/.test(item.align[i])) {
56521           item.align[i] = 'center';
56522         } else if (/^ *:-+ *$/.test(item.align[i])) {
56523           item.align[i] = 'left';
56524         } else {
56525           item.align[i] = null;
56526         }
56527       }
56528
56529       for (i = 0; i < item.cells.length; i++) {
56530         item.cells[i] = item.cells[i].split(/ *\| */);
56531       }
56532
56533       this.tokens.push(item);
56534
56535       continue;
56536     }
56537
56538     // lheading
56539     if (cap = this.rules.lheading.exec(src)) {
56540       src = src.substring(cap[0].length);
56541       this.tokens.push({
56542         type: 'heading',
56543         depth: cap[2] === '=' ? 1 : 2,
56544         text: cap[1]
56545       });
56546       continue;
56547     }
56548
56549     // hr
56550     if (cap = this.rules.hr.exec(src)) {
56551       src = src.substring(cap[0].length);
56552       this.tokens.push({
56553         type: 'hr'
56554       });
56555       continue;
56556     }
56557
56558     // blockquote
56559     if (cap = this.rules.blockquote.exec(src)) {
56560       src = src.substring(cap[0].length);
56561
56562       this.tokens.push({
56563         type: 'blockquote_start'
56564       });
56565
56566       cap = cap[0].replace(/^ *> ?/gm, '');
56567
56568       // Pass `top` to keep the current
56569       // "toplevel" state. This is exactly
56570       // how markdown.pl works.
56571       this.token(cap, top, true);
56572
56573       this.tokens.push({
56574         type: 'blockquote_end'
56575       });
56576
56577       continue;
56578     }
56579
56580     // list
56581     if (cap = this.rules.list.exec(src)) {
56582       src = src.substring(cap[0].length);
56583       bull = cap[2];
56584
56585       this.tokens.push({
56586         type: 'list_start',
56587         ordered: bull.length > 1
56588       });
56589
56590       // Get each top-level item.
56591       cap = cap[0].match(this.rules.item);
56592
56593       next = false;
56594       l = cap.length;
56595       i = 0;
56596
56597       for (; i < l; i++) {
56598         item = cap[i];
56599
56600         // Remove the list item's bullet
56601         // so it is seen as the next token.
56602         space = item.length;
56603         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
56604
56605         // Outdent whatever the
56606         // list item contains. Hacky.
56607         if (~item.indexOf('\n ')) {
56608           space -= item.length;
56609           item = !this.options.pedantic
56610             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
56611             : item.replace(/^ {1,4}/gm, '');
56612         }
56613
56614         // Determine whether the next list item belongs here.
56615         // Backpedal if it does not belong in this list.
56616         if (this.options.smartLists && i !== l - 1) {
56617           b = block.bullet.exec(cap[i + 1])[0];
56618           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
56619             src = cap.slice(i + 1).join('\n') + src;
56620             i = l - 1;
56621           }
56622         }
56623
56624         // Determine whether item is loose or not.
56625         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
56626         // for discount behavior.
56627         loose = next || /\n\n(?!\s*$)/.test(item);
56628         if (i !== l - 1) {
56629           next = item.charAt(item.length - 1) === '\n';
56630           if (!loose) loose = next;
56631         }
56632
56633         this.tokens.push({
56634           type: loose
56635             ? 'loose_item_start'
56636             : 'list_item_start'
56637         });
56638
56639         // Recurse.
56640         this.token(item, false, bq);
56641
56642         this.tokens.push({
56643           type: 'list_item_end'
56644         });
56645       }
56646
56647       this.tokens.push({
56648         type: 'list_end'
56649       });
56650
56651       continue;
56652     }
56653
56654     // html
56655     if (cap = this.rules.html.exec(src)) {
56656       src = src.substring(cap[0].length);
56657       this.tokens.push({
56658         type: this.options.sanitize
56659           ? 'paragraph'
56660           : 'html',
56661         pre: !this.options.sanitizer
56662           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
56663         text: cap[0]
56664       });
56665       continue;
56666     }
56667
56668     // def
56669     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
56670       src = src.substring(cap[0].length);
56671       this.tokens.links[cap[1].toLowerCase()] = {
56672         href: cap[2],
56673         title: cap[3]
56674       };
56675       continue;
56676     }
56677
56678     // table (gfm)
56679     if (top && (cap = this.rules.table.exec(src))) {
56680       src = src.substring(cap[0].length);
56681
56682       item = {
56683         type: 'table',
56684         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56685         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56686         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
56687       };
56688
56689       for (i = 0; i < item.align.length; i++) {
56690         if (/^ *-+: *$/.test(item.align[i])) {
56691           item.align[i] = 'right';
56692         } else if (/^ *:-+: *$/.test(item.align[i])) {
56693           item.align[i] = 'center';
56694         } else if (/^ *:-+ *$/.test(item.align[i])) {
56695           item.align[i] = 'left';
56696         } else {
56697           item.align[i] = null;
56698         }
56699       }
56700
56701       for (i = 0; i < item.cells.length; i++) {
56702         item.cells[i] = item.cells[i]
56703           .replace(/^ *\| *| *\| *$/g, '')
56704           .split(/ *\| */);
56705       }
56706
56707       this.tokens.push(item);
56708
56709       continue;
56710     }
56711
56712     // top-level paragraph
56713     if (top && (cap = this.rules.paragraph.exec(src))) {
56714       src = src.substring(cap[0].length);
56715       this.tokens.push({
56716         type: 'paragraph',
56717         text: cap[1].charAt(cap[1].length - 1) === '\n'
56718           ? cap[1].slice(0, -1)
56719           : cap[1]
56720       });
56721       continue;
56722     }
56723
56724     // text
56725     if (cap = this.rules.text.exec(src)) {
56726       // Top-level should never reach here.
56727       src = src.substring(cap[0].length);
56728       this.tokens.push({
56729         type: 'text',
56730         text: cap[0]
56731       });
56732       continue;
56733     }
56734
56735     if (src) {
56736       throw new
56737         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56738     }
56739   }
56740
56741   return this.tokens;
56742 };
56743
56744 /**
56745  * Inline-Level Grammar
56746  */
56747
56748 var inline = {
56749   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
56750   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
56751   url: noop,
56752   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
56753   link: /^!?\[(inside)\]\(href\)/,
56754   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
56755   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
56756   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
56757   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
56758   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
56759   br: /^ {2,}\n(?!\s*$)/,
56760   del: noop,
56761   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
56762 };
56763
56764 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
56765 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
56766
56767 inline.link = replace(inline.link)
56768   ('inside', inline._inside)
56769   ('href', inline._href)
56770   ();
56771
56772 inline.reflink = replace(inline.reflink)
56773   ('inside', inline._inside)
56774   ();
56775
56776 /**
56777  * Normal Inline Grammar
56778  */
56779
56780 inline.normal = merge({}, inline);
56781
56782 /**
56783  * Pedantic Inline Grammar
56784  */
56785
56786 inline.pedantic = merge({}, inline.normal, {
56787   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
56788   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
56789 });
56790
56791 /**
56792  * GFM Inline Grammar
56793  */
56794
56795 inline.gfm = merge({}, inline.normal, {
56796   escape: replace(inline.escape)('])', '~|])')(),
56797   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
56798   del: /^~~(?=\S)([\s\S]*?\S)~~/,
56799   text: replace(inline.text)
56800     (']|', '~]|')
56801     ('|', '|https?://|')
56802     ()
56803 });
56804
56805 /**
56806  * GFM + Line Breaks Inline Grammar
56807  */
56808
56809 inline.breaks = merge({}, inline.gfm, {
56810   br: replace(inline.br)('{2,}', '*')(),
56811   text: replace(inline.gfm.text)('{2,}', '*')()
56812 });
56813
56814 /**
56815  * Inline Lexer & Compiler
56816  */
56817
56818 function InlineLexer(links, options) {
56819   this.options = options || marked.defaults;
56820   this.links = links;
56821   this.rules = inline.normal;
56822   this.renderer = this.options.renderer || new Renderer;
56823   this.renderer.options = this.options;
56824
56825   if (!this.links) {
56826     throw new
56827       Error('Tokens array requires a `links` property.');
56828   }
56829
56830   if (this.options.gfm) {
56831     if (this.options.breaks) {
56832       this.rules = inline.breaks;
56833     } else {
56834       this.rules = inline.gfm;
56835     }
56836   } else if (this.options.pedantic) {
56837     this.rules = inline.pedantic;
56838   }
56839 }
56840
56841 /**
56842  * Expose Inline Rules
56843  */
56844
56845 InlineLexer.rules = inline;
56846
56847 /**
56848  * Static Lexing/Compiling Method
56849  */
56850
56851 InlineLexer.output = function(src, links, options) {
56852   var inline = new InlineLexer(links, options);
56853   return inline.output(src);
56854 };
56855
56856 /**
56857  * Lexing/Compiling
56858  */
56859
56860 InlineLexer.prototype.output = function(src) {
56861   var out = ''
56862     , link
56863     , text
56864     , href
56865     , cap;
56866
56867   while (src) {
56868     // escape
56869     if (cap = this.rules.escape.exec(src)) {
56870       src = src.substring(cap[0].length);
56871       out += cap[1];
56872       continue;
56873     }
56874
56875     // autolink
56876     if (cap = this.rules.autolink.exec(src)) {
56877       src = src.substring(cap[0].length);
56878       if (cap[2] === '@') {
56879         text = cap[1].charAt(6) === ':'
56880           ? this.mangle(cap[1].substring(7))
56881           : this.mangle(cap[1]);
56882         href = this.mangle('mailto:') + text;
56883       } else {
56884         text = escape(cap[1]);
56885         href = text;
56886       }
56887       out += this.renderer.link(href, null, text);
56888       continue;
56889     }
56890
56891     // url (gfm)
56892     if (!this.inLink && (cap = this.rules.url.exec(src))) {
56893       src = src.substring(cap[0].length);
56894       text = escape(cap[1]);
56895       href = text;
56896       out += this.renderer.link(href, null, text);
56897       continue;
56898     }
56899
56900     // tag
56901     if (cap = this.rules.tag.exec(src)) {
56902       if (!this.inLink && /^<a /i.test(cap[0])) {
56903         this.inLink = true;
56904       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
56905         this.inLink = false;
56906       }
56907       src = src.substring(cap[0].length);
56908       out += this.options.sanitize
56909         ? this.options.sanitizer
56910           ? this.options.sanitizer(cap[0])
56911           : escape(cap[0])
56912         : cap[0];
56913       continue;
56914     }
56915
56916     // link
56917     if (cap = this.rules.link.exec(src)) {
56918       src = src.substring(cap[0].length);
56919       this.inLink = true;
56920       out += this.outputLink(cap, {
56921         href: cap[2],
56922         title: cap[3]
56923       });
56924       this.inLink = false;
56925       continue;
56926     }
56927
56928     // reflink, nolink
56929     if ((cap = this.rules.reflink.exec(src))
56930         || (cap = this.rules.nolink.exec(src))) {
56931       src = src.substring(cap[0].length);
56932       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
56933       link = this.links[link.toLowerCase()];
56934       if (!link || !link.href) {
56935         out += cap[0].charAt(0);
56936         src = cap[0].substring(1) + src;
56937         continue;
56938       }
56939       this.inLink = true;
56940       out += this.outputLink(cap, link);
56941       this.inLink = false;
56942       continue;
56943     }
56944
56945     // strong
56946     if (cap = this.rules.strong.exec(src)) {
56947       src = src.substring(cap[0].length);
56948       out += this.renderer.strong(this.output(cap[2] || cap[1]));
56949       continue;
56950     }
56951
56952     // em
56953     if (cap = this.rules.em.exec(src)) {
56954       src = src.substring(cap[0].length);
56955       out += this.renderer.em(this.output(cap[2] || cap[1]));
56956       continue;
56957     }
56958
56959     // code
56960     if (cap = this.rules.code.exec(src)) {
56961       src = src.substring(cap[0].length);
56962       out += this.renderer.codespan(escape(cap[2], true));
56963       continue;
56964     }
56965
56966     // br
56967     if (cap = this.rules.br.exec(src)) {
56968       src = src.substring(cap[0].length);
56969       out += this.renderer.br();
56970       continue;
56971     }
56972
56973     // del (gfm)
56974     if (cap = this.rules.del.exec(src)) {
56975       src = src.substring(cap[0].length);
56976       out += this.renderer.del(this.output(cap[1]));
56977       continue;
56978     }
56979
56980     // text
56981     if (cap = this.rules.text.exec(src)) {
56982       src = src.substring(cap[0].length);
56983       out += this.renderer.text(escape(this.smartypants(cap[0])));
56984       continue;
56985     }
56986
56987     if (src) {
56988       throw new
56989         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56990     }
56991   }
56992
56993   return out;
56994 };
56995
56996 /**
56997  * Compile Link
56998  */
56999
57000 InlineLexer.prototype.outputLink = function(cap, link) {
57001   var href = escape(link.href)
57002     , title = link.title ? escape(link.title) : null;
57003
57004   return cap[0].charAt(0) !== '!'
57005     ? this.renderer.link(href, title, this.output(cap[1]))
57006     : this.renderer.image(href, title, escape(cap[1]));
57007 };
57008
57009 /**
57010  * Smartypants Transformations
57011  */
57012
57013 InlineLexer.prototype.smartypants = function(text) {
57014   if (!this.options.smartypants) return text;
57015   return text
57016     // em-dashes
57017     .replace(/---/g, '\u2014')
57018     // en-dashes
57019     .replace(/--/g, '\u2013')
57020     // opening singles
57021     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
57022     // closing singles & apostrophes
57023     .replace(/'/g, '\u2019')
57024     // opening doubles
57025     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
57026     // closing doubles
57027     .replace(/"/g, '\u201d')
57028     // ellipses
57029     .replace(/\.{3}/g, '\u2026');
57030 };
57031
57032 /**
57033  * Mangle Links
57034  */
57035
57036 InlineLexer.prototype.mangle = function(text) {
57037   if (!this.options.mangle) return text;
57038   var out = ''
57039     , l = text.length
57040     , i = 0
57041     , ch;
57042
57043   for (; i < l; i++) {
57044     ch = text.charCodeAt(i);
57045     if (Math.random() > 0.5) {
57046       ch = 'x' + ch.toString(16);
57047     }
57048     out += '&#' + ch + ';';
57049   }
57050
57051   return out;
57052 };
57053
57054 /**
57055  * Renderer
57056  */
57057
57058 function Renderer(options) {
57059   this.options = options || {};
57060 }
57061
57062 Renderer.prototype.code = function(code, lang, escaped) {
57063   if (this.options.highlight) {
57064     var out = this.options.highlight(code, lang);
57065     if (out != null && out !== code) {
57066       escaped = true;
57067       code = out;
57068     }
57069   }
57070
57071   if (!lang) {
57072     return '<pre><code>'
57073       + (escaped ? code : escape(code, true))
57074       + '\n</code></pre>';
57075   }
57076
57077   return '<pre><code class="'
57078     + this.options.langPrefix
57079     + escape(lang, true)
57080     + '">'
57081     + (escaped ? code : escape(code, true))
57082     + '\n</code></pre>\n';
57083 };
57084
57085 Renderer.prototype.blockquote = function(quote) {
57086   return '<blockquote>\n' + quote + '</blockquote>\n';
57087 };
57088
57089 Renderer.prototype.html = function(html) {
57090   return html;
57091 };
57092
57093 Renderer.prototype.heading = function(text, level, raw) {
57094   return '<h'
57095     + level
57096     + ' id="'
57097     + this.options.headerPrefix
57098     + raw.toLowerCase().replace(/[^\w]+/g, '-')
57099     + '">'
57100     + text
57101     + '</h'
57102     + level
57103     + '>\n';
57104 };
57105
57106 Renderer.prototype.hr = function() {
57107   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
57108 };
57109
57110 Renderer.prototype.list = function(body, ordered) {
57111   var type = ordered ? 'ol' : 'ul';
57112   return '<' + type + '>\n' + body + '</' + type + '>\n';
57113 };
57114
57115 Renderer.prototype.listitem = function(text) {
57116   return '<li>' + text + '</li>\n';
57117 };
57118
57119 Renderer.prototype.paragraph = function(text) {
57120   return '<p>' + text + '</p>\n';
57121 };
57122
57123 Renderer.prototype.table = function(header, body) {
57124   return '<table>\n'
57125     + '<thead>\n'
57126     + header
57127     + '</thead>\n'
57128     + '<tbody>\n'
57129     + body
57130     + '</tbody>\n'
57131     + '</table>\n';
57132 };
57133
57134 Renderer.prototype.tablerow = function(content) {
57135   return '<tr>\n' + content + '</tr>\n';
57136 };
57137
57138 Renderer.prototype.tablecell = function(content, flags) {
57139   var type = flags.header ? 'th' : 'td';
57140   var tag = flags.align
57141     ? '<' + type + ' style="text-align:' + flags.align + '">'
57142     : '<' + type + '>';
57143   return tag + content + '</' + type + '>\n';
57144 };
57145
57146 // span level renderer
57147 Renderer.prototype.strong = function(text) {
57148   return '<strong>' + text + '</strong>';
57149 };
57150
57151 Renderer.prototype.em = function(text) {
57152   return '<em>' + text + '</em>';
57153 };
57154
57155 Renderer.prototype.codespan = function(text) {
57156   return '<code>' + text + '</code>';
57157 };
57158
57159 Renderer.prototype.br = function() {
57160   return this.options.xhtml ? '<br/>' : '<br>';
57161 };
57162
57163 Renderer.prototype.del = function(text) {
57164   return '<del>' + text + '</del>';
57165 };
57166
57167 Renderer.prototype.link = function(href, title, text) {
57168   if (this.options.sanitize) {
57169     try {
57170       var prot = decodeURIComponent(unescape(href))
57171         .replace(/[^\w:]/g, '')
57172         .toLowerCase();
57173     } catch (e) {
57174       return '';
57175     }
57176     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
57177       return '';
57178     }
57179   }
57180   var out = '<a href="' + href + '"';
57181   if (title) {
57182     out += ' title="' + title + '"';
57183   }
57184   out += '>' + text + '</a>';
57185   return out;
57186 };
57187
57188 Renderer.prototype.image = function(href, title, text) {
57189   var out = '<img src="' + href + '" alt="' + text + '"';
57190   if (title) {
57191     out += ' title="' + title + '"';
57192   }
57193   out += this.options.xhtml ? '/>' : '>';
57194   return out;
57195 };
57196
57197 Renderer.prototype.text = function(text) {
57198   return text;
57199 };
57200
57201 /**
57202  * Parsing & Compiling
57203  */
57204
57205 function Parser(options) {
57206   this.tokens = [];
57207   this.token = null;
57208   this.options = options || marked.defaults;
57209   this.options.renderer = this.options.renderer || new Renderer;
57210   this.renderer = this.options.renderer;
57211   this.renderer.options = this.options;
57212 }
57213
57214 /**
57215  * Static Parse Method
57216  */
57217
57218 Parser.parse = function(src, options, renderer) {
57219   var parser = new Parser(options, renderer);
57220   return parser.parse(src);
57221 };
57222
57223 /**
57224  * Parse Loop
57225  */
57226
57227 Parser.prototype.parse = function(src) {
57228   this.inline = new InlineLexer(src.links, this.options, this.renderer);
57229   this.tokens = src.reverse();
57230
57231   var out = '';
57232   while (this.next()) {
57233     out += this.tok();
57234   }
57235
57236   return out;
57237 };
57238
57239 /**
57240  * Next Token
57241  */
57242
57243 Parser.prototype.next = function() {
57244   return this.token = this.tokens.pop();
57245 };
57246
57247 /**
57248  * Preview Next Token
57249  */
57250
57251 Parser.prototype.peek = function() {
57252   return this.tokens[this.tokens.length - 1] || 0;
57253 };
57254
57255 /**
57256  * Parse Text Tokens
57257  */
57258
57259 Parser.prototype.parseText = function() {
57260   var body = this.token.text;
57261
57262   while (this.peek().type === 'text') {
57263     body += '\n' + this.next().text;
57264   }
57265
57266   return this.inline.output(body);
57267 };
57268
57269 /**
57270  * Parse Current Token
57271  */
57272
57273 Parser.prototype.tok = function() {
57274   switch (this.token.type) {
57275     case 'space': {
57276       return '';
57277     }
57278     case 'hr': {
57279       return this.renderer.hr();
57280     }
57281     case 'heading': {
57282       return this.renderer.heading(
57283         this.inline.output(this.token.text),
57284         this.token.depth,
57285         this.token.text);
57286     }
57287     case 'code': {
57288       return this.renderer.code(this.token.text,
57289         this.token.lang,
57290         this.token.escaped);
57291     }
57292     case 'table': {
57293       var header = ''
57294         , body = ''
57295         , i
57296         , row
57297         , cell
57298         , flags
57299         , j;
57300
57301       // header
57302       cell = '';
57303       for (i = 0; i < this.token.header.length; i++) {
57304         flags = { header: true, align: this.token.align[i] };
57305         cell += this.renderer.tablecell(
57306           this.inline.output(this.token.header[i]),
57307           { header: true, align: this.token.align[i] }
57308         );
57309       }
57310       header += this.renderer.tablerow(cell);
57311
57312       for (i = 0; i < this.token.cells.length; i++) {
57313         row = this.token.cells[i];
57314
57315         cell = '';
57316         for (j = 0; j < row.length; j++) {
57317           cell += this.renderer.tablecell(
57318             this.inline.output(row[j]),
57319             { header: false, align: this.token.align[j] }
57320           );
57321         }
57322
57323         body += this.renderer.tablerow(cell);
57324       }
57325       return this.renderer.table(header, body);
57326     }
57327     case 'blockquote_start': {
57328       var body = '';
57329
57330       while (this.next().type !== 'blockquote_end') {
57331         body += this.tok();
57332       }
57333
57334       return this.renderer.blockquote(body);
57335     }
57336     case 'list_start': {
57337       var body = ''
57338         , ordered = this.token.ordered;
57339
57340       while (this.next().type !== 'list_end') {
57341         body += this.tok();
57342       }
57343
57344       return this.renderer.list(body, ordered);
57345     }
57346     case 'list_item_start': {
57347       var body = '';
57348
57349       while (this.next().type !== 'list_item_end') {
57350         body += this.token.type === 'text'
57351           ? this.parseText()
57352           : this.tok();
57353       }
57354
57355       return this.renderer.listitem(body);
57356     }
57357     case 'loose_item_start': {
57358       var body = '';
57359
57360       while (this.next().type !== 'list_item_end') {
57361         body += this.tok();
57362       }
57363
57364       return this.renderer.listitem(body);
57365     }
57366     case 'html': {
57367       var html = !this.token.pre && !this.options.pedantic
57368         ? this.inline.output(this.token.text)
57369         : this.token.text;
57370       return this.renderer.html(html);
57371     }
57372     case 'paragraph': {
57373       return this.renderer.paragraph(this.inline.output(this.token.text));
57374     }
57375     case 'text': {
57376       return this.renderer.paragraph(this.parseText());
57377     }
57378   }
57379 };
57380
57381 /**
57382  * Helpers
57383  */
57384
57385 function escape(html, encode) {
57386   return html
57387     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
57388     .replace(/</g, '&lt;')
57389     .replace(/>/g, '&gt;')
57390     .replace(/"/g, '&quot;')
57391     .replace(/'/g, '&#39;');
57392 }
57393
57394 function unescape(html) {
57395         // explicitly match decimal, hex, and named HTML entities 
57396   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
57397     n = n.toLowerCase();
57398     if (n === 'colon') return ':';
57399     if (n.charAt(0) === '#') {
57400       return n.charAt(1) === 'x'
57401         ? String.fromCharCode(parseInt(n.substring(2), 16))
57402         : String.fromCharCode(+n.substring(1));
57403     }
57404     return '';
57405   });
57406 }
57407
57408 function replace(regex, opt) {
57409   regex = regex.source;
57410   opt = opt || '';
57411   return function self(name, val) {
57412     if (!name) return new RegExp(regex, opt);
57413     val = val.source || val;
57414     val = val.replace(/(^|[^\[])\^/g, '$1');
57415     regex = regex.replace(name, val);
57416     return self;
57417   };
57418 }
57419
57420 function noop() {}
57421 noop.exec = noop;
57422
57423 function merge(obj) {
57424   var i = 1
57425     , target
57426     , key;
57427
57428   for (; i < arguments.length; i++) {
57429     target = arguments[i];
57430     for (key in target) {
57431       if (Object.prototype.hasOwnProperty.call(target, key)) {
57432         obj[key] = target[key];
57433       }
57434     }
57435   }
57436
57437   return obj;
57438 }
57439
57440
57441 /**
57442  * Marked
57443  */
57444
57445 function marked(src, opt, callback) {
57446   if (callback || typeof opt === 'function') {
57447     if (!callback) {
57448       callback = opt;
57449       opt = null;
57450     }
57451
57452     opt = merge({}, marked.defaults, opt || {});
57453
57454     var highlight = opt.highlight
57455       , tokens
57456       , pending
57457       , i = 0;
57458
57459     try {
57460       tokens = Lexer.lex(src, opt);
57461     } catch (e) {
57462       return callback(e);
57463     }
57464
57465     pending = tokens.length;
57466
57467     var done = function(err) {
57468       if (err) {
57469         opt.highlight = highlight;
57470         return callback(err);
57471       }
57472
57473       var out;
57474
57475       try {
57476         out = Parser.parse(tokens, opt);
57477       } catch (e) {
57478         err = e;
57479       }
57480
57481       opt.highlight = highlight;
57482
57483       return err
57484         ? callback(err)
57485         : callback(null, out);
57486     };
57487
57488     if (!highlight || highlight.length < 3) {
57489       return done();
57490     }
57491
57492     delete opt.highlight;
57493
57494     if (!pending) return done();
57495
57496     for (; i < tokens.length; i++) {
57497       (function(token) {
57498         if (token.type !== 'code') {
57499           return --pending || done();
57500         }
57501         return highlight(token.text, token.lang, function(err, code) {
57502           if (err) return done(err);
57503           if (code == null || code === token.text) {
57504             return --pending || done();
57505           }
57506           token.text = code;
57507           token.escaped = true;
57508           --pending || done();
57509         });
57510       })(tokens[i]);
57511     }
57512
57513     return;
57514   }
57515   try {
57516     if (opt) opt = merge({}, marked.defaults, opt);
57517     return Parser.parse(Lexer.lex(src, opt), opt);
57518   } catch (e) {
57519     e.message += '\nPlease report this to https://github.com/chjj/marked.';
57520     if ((opt || marked.defaults).silent) {
57521       return '<p>An error occured:</p><pre>'
57522         + escape(e.message + '', true)
57523         + '</pre>';
57524     }
57525     throw e;
57526   }
57527 }
57528
57529 /**
57530  * Options
57531  */
57532
57533 marked.options =
57534 marked.setOptions = function(opt) {
57535   merge(marked.defaults, opt);
57536   return marked;
57537 };
57538
57539 marked.defaults = {
57540   gfm: true,
57541   tables: true,
57542   breaks: false,
57543   pedantic: false,
57544   sanitize: false,
57545   sanitizer: null,
57546   mangle: true,
57547   smartLists: false,
57548   silent: false,
57549   highlight: null,
57550   langPrefix: 'lang-',
57551   smartypants: false,
57552   headerPrefix: '',
57553   renderer: new Renderer,
57554   xhtml: false
57555 };
57556
57557 /**
57558  * Expose
57559  */
57560
57561 marked.Parser = Parser;
57562 marked.parser = Parser.parse;
57563
57564 marked.Renderer = Renderer;
57565
57566 marked.Lexer = Lexer;
57567 marked.lexer = Lexer.lex;
57568
57569 marked.InlineLexer = InlineLexer;
57570 marked.inlineLexer = InlineLexer.output;
57571
57572 marked.parse = marked;
57573
57574 {
57575   module.exports = marked;
57576 }
57577
57578 }).call(function() {
57579   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
57580 }());
57581 });
57582
57583 // toggles the visibility of ui elements, using a combination of the
57584 // hide class, which sets display=none, and a d3 transition for opacity.
57585 // this will cause blinking when called repeatedly, so check that the
57586 // value actually changes between calls.
57587 function uiToggle(show, callback) {
57588     return function(selection$$1) {
57589         selection$$1
57590             .style('opacity', show ? 0 : 1)
57591             .classed('hide', false)
57592             .transition()
57593             .style('opacity', show ? 1 : 0)
57594             .on('end', function() {
57595                 select(this)
57596                     .classed('hide', !show)
57597                     .style('opacity', null);
57598                 if (callback) callback.apply(this);
57599             });
57600     };
57601 }
57602
57603 // Tooltips and svg mask used to highlight certain features
57604 function d3curtain() {
57605
57606     var dispatch$$1 = dispatch(),
57607         surface = select(null),
57608         tooltip = select(null),
57609         darkness = select(null);
57610
57611     function curtain(selection$$1) {
57612         surface = selection$$1
57613             .append('svg')
57614             .attr('id', 'curtain')
57615             .style('z-index', 1000)
57616             .style('pointer-events', 'none')
57617             .style('position', 'absolute')
57618             .style('top', 0)
57619             .style('left', 0);
57620
57621         darkness = surface.append('path')
57622             .attr('x', 0)
57623             .attr('y', 0)
57624             .attr('class', 'curtain-darkness');
57625
57626         select(window).on('resize.curtain', resize);
57627
57628         tooltip = selection$$1.append('div')
57629             .attr('class', 'tooltip')
57630             .style('z-index', 1002);
57631
57632         tooltip
57633             .append('div')
57634             .attr('class', 'tooltip-arrow');
57635
57636         tooltip
57637             .append('div')
57638             .attr('class', 'tooltip-inner');
57639
57640         resize();
57641
57642
57643         function resize() {
57644             surface
57645                 .attr('width', window.innerWidth)
57646                 .attr('height', window.innerHeight);
57647             curtain.cut(darkness.datum());
57648         }
57649     }
57650
57651
57652     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
57653         if (typeof box === 'string') box = select(box).node();
57654         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
57655
57656         curtain.cut(box, duration);
57657
57658         if (text$$1) {
57659             // pseudo markdown bold text hack
57660             var parts = text$$1.split('**');
57661             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
57662             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
57663
57664             var selection$$1 = tooltip
57665                 .classed('in', true)
57666                 .selectAll('.tooltip-inner')
57667                 .html(html$$1);
57668
57669             var dimensions = utilGetDimensions(selection$$1, true),
57670                 w = window.innerWidth,
57671                 h = window.innerHeight,
57672                 side, pos;
57673
57674             // trim box dimensions to just the portion that fits in the window..
57675             if (box.top + box.height > h) {
57676                 box.height -= (box.top + box.height - h);
57677             }
57678             if (box.left + box.width > w) {
57679                 box.width -= (box.left + box.width - w);
57680             }
57681
57682             // determine tooltip placement..
57683             if (box.top + box.height < Math.min(100, box.width + box.left)) {
57684                 side = 'bottom';
57685                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
57686
57687             } else if (box.left + box.width + 300 < w) {
57688                 side = 'right';
57689                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
57690
57691             } else if (box.left > 300) {
57692                 side = 'left';
57693                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
57694
57695             } else {
57696                 side = 'bottom';
57697                 pos = [box.left, box.top + box.height];
57698             }
57699
57700             pos = [
57701                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
57702                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
57703             ];
57704
57705             if (duration !== 0 || !tooltip.classed(side)) {
57706                 tooltip.call(uiToggle(true));
57707             }
57708
57709             tooltip
57710                 .style('top', pos[1] + 'px')
57711                 .style('left', pos[0] + 'px')
57712                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
57713
57714         } else {
57715             tooltip.call(uiToggle(false));
57716         }
57717     };
57718
57719
57720     curtain.cut = function(datum, duration) {
57721         darkness.datum(datum)
57722             .interrupt();
57723
57724         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
57725             .attr('d', function(d) {
57726                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
57727                     window.innerWidth + ',' + window.innerHeight + 'L' +
57728                     window.innerWidth + ',0 Z';
57729
57730                 if (!d) return string;
57731                 return string + 'M' +
57732                     d.left + ',' + d.top + 'L' +
57733                     d.left + ',' + (d.top + d.height) + 'L' +
57734                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
57735                     (d.left + d.width) + ',' + (d.top) + 'Z';
57736
57737             });
57738     };
57739
57740
57741     curtain.remove = function() {
57742         surface.remove();
57743         tooltip.remove();
57744     };
57745
57746
57747     return utilRebind(curtain, dispatch$$1, 'on');
57748 }
57749
57750 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"]}};
57751
57752 function pointBox(point, context) {
57753     var rect = context.surfaceRect();
57754     point = context.projection(point);
57755     return {
57756         left: point[0] + rect.left - 30,
57757         top: point[1] + rect.top - 50,
57758         width: 60,
57759         height: 70
57760      };
57761 }
57762
57763
57764 function pad$1(box, padding, context) {
57765     if (box instanceof Array) {
57766         var rect = context.surfaceRect();
57767         box = context.projection(box);
57768         box = {
57769             left: box[0] + rect.left,
57770             top: box[1] + rect.top
57771         };
57772     }
57773     return {
57774         left: box.left - padding,
57775         top: box.top - padding,
57776         width: (box.width || 0) + 2 * padding,
57777         height: (box.width || 0) + 2 * padding
57778     };
57779 }
57780
57781
57782 function icon(name, svgklass) {
57783     return '<svg class="icon ' + (svgklass || '') + '">' +
57784          '<use xlink:href="' + name + '"></use></svg>';
57785  }
57786
57787 function uiIntroNavigation(context, reveal) {
57788     var dispatch$$1 = dispatch('done'),
57789         timeouts = [];
57790
57791     var step = {
57792         title: 'intro.navigation.title'
57793     };
57794
57795
57796     function set$$1(f, t$$1) {
57797         timeouts.push(window.setTimeout(f, t$$1));
57798     }
57799
57800
57801     function eventCancel() {
57802         event.stopPropagation();
57803         event.preventDefault();
57804     }
57805
57806
57807     step.enter = function() {
57808         var rect = context.surfaceRect(),
57809             map$$1 = {
57810                 left: rect.left + 10,
57811                 top: rect.top + 70,
57812                 width: rect.width - 70,
57813                 height: rect.height - 170
57814             };
57815
57816         context.map().centerZoom([-85.63591, 41.94285], 19);
57817
57818         reveal(map$$1, t('intro.navigation.drag'));
57819
57820         context.map().on('move.intro', lodash.debounce(function() {
57821             context.map().on('move.intro', null);
57822             townhall();
57823             context.on('enter.intro', inspectTownHall);
57824         }, 400));
57825
57826
57827         function townhall() {
57828             var hall = [-85.63645945147184, 41.942986488012565];
57829             var point = context.projection(hall);
57830
57831             if (point[0] < 0 || point[0] > rect.width ||
57832                 point[1] < 0 || point[1] > rect.height) {
57833                 context.map().center(hall);
57834             }
57835
57836             var box = pointBox(hall, context);
57837             reveal(box, t('intro.navigation.select'));
57838
57839             context.map().on('move.intro', function() {
57840                 var box = pointBox(hall, context);
57841                 reveal(box, t('intro.navigation.select'), {duration: 0});
57842             });
57843         }
57844
57845
57846         function inspectTownHall(mode) {
57847             if (mode.id !== 'select') return;
57848             context.on('enter.intro', null);
57849             context.map().on('move.intro', null);
57850             set$$1(function() {
57851                 reveal('.entity-editor-pane',
57852                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
57853                 context.on('exit.intro', streetSearch);
57854             }, 700);
57855         }
57856
57857
57858         function streetSearch() {
57859             context.on('exit.intro', null);
57860             reveal('.search-header input',
57861                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
57862             select('.search-header input')
57863                 .on('keyup.intro', searchResult);
57864         }
57865
57866
57867         function searchResult() {
57868             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
57869                 firstName = first.select('.entity-name'),
57870                 name = t('intro.graph.spring_st');
57871
57872             if (!firstName.empty() && firstName.text() === name) {
57873                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
57874                 context.on('exit.intro', selectedStreet);
57875                 select('.search-header input')
57876                     .on('keydown.intro', eventCancel, true)
57877                     .on('keyup.intro', null);
57878             }
57879         }
57880
57881
57882         function selectedStreet() {
57883             var springSt = [-85.63585099140167, 41.942506848938926];
57884             context.map().center(springSt);
57885             context.on('exit.intro', function() {
57886                 dispatch$$1.call('done');
57887             });
57888
57889             set$$1(function() {
57890                 reveal('.entity-editor-pane',
57891                     t('intro.navigation.chosen', {
57892                         name: t('intro.graph.spring_st'),
57893                         button: icon('#icon-close', 'pre-text')
57894                     }));
57895             }, 400);
57896         }
57897     };
57898
57899
57900     step.exit = function() {
57901         timeouts.forEach(window.clearTimeout);
57902         context.map().on('move.intro', null);
57903         context.on('enter.intro', null);
57904         context.on('exit.intro', null);
57905         select('.search-header input')
57906             .on('keydown.intro', null)
57907             .on('keyup.intro', null);
57908     };
57909
57910
57911     return utilRebind(step, dispatch$$1, 'on');
57912 }
57913
57914 function uiIntroPoint(context, reveal) {
57915     var dispatch$$1 = dispatch('done'),
57916         timeouts = [];
57917
57918     var step = {
57919         title: 'intro.points.title'
57920     };
57921
57922
57923     function setTimeout(f, t$$1) {
57924         timeouts.push(window.setTimeout(f, t$$1));
57925     }
57926
57927
57928     function eventCancel() {
57929         event.stopPropagation();
57930         event.preventDefault();
57931     }
57932
57933
57934     step.enter = function() {
57935         context.map().centerZoom([-85.63279, 41.94394], 19);
57936         reveal('button.add-point',
57937             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
57938             { tooltipClass: 'intro-points-add' });
57939
57940         var corner = [-85.632481,41.944094];
57941
57942         context.on('enter.intro', addPoint);
57943
57944
57945         function addPoint(mode) {
57946             if (mode.id !== 'add-point') return;
57947             context.on('enter.intro', enterSelect);
57948
57949             var pointBox$$1 = pad$1(corner, 150, context);
57950             reveal(pointBox$$1, t('intro.points.place'));
57951
57952             context.map().on('move.intro', function() {
57953                 pointBox$$1 = pad$1(corner, 150, context);
57954                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
57955             });
57956         }
57957
57958
57959         function enterSelect(mode) {
57960             if (mode.id !== 'select') return;
57961             context.map().on('move.intro', null);
57962             context.on('enter.intro', null);
57963
57964             setTimeout(function() {
57965                 reveal('.preset-search-input',
57966                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
57967                 select('.preset-search-input').on('keyup.intro', keySearch);
57968             }, 500);
57969         }
57970
57971
57972         function keySearch() {
57973             var first = select('.preset-list-item:first-child');
57974             if (first.classed('preset-amenity-cafe')) {
57975                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
57976                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57977                 select('.preset-search-input')
57978                     .on('keydown.intro', eventCancel, true)
57979                     .on('keyup.intro', null);
57980             }
57981         }
57982
57983
57984         function selectedPreset() {
57985             setTimeout(function() {
57986                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
57987                 context.history().on('change.intro', closeEditor);
57988                 context.on('exit.intro', selectPoint);
57989             }, 400);
57990         }
57991
57992
57993         function closeEditor() {
57994             select('.preset-search-input').on('keydown.intro', null);
57995             context.history().on('change.intro', null);
57996             reveal('.entity-editor-pane',
57997                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
57998         }
57999
58000
58001         function selectPoint() {
58002             context.on('exit.intro', null);
58003             context.history().on('change.intro', null);
58004             context.on('enter.intro', enterReselect);
58005
58006             var pointBox$$1 = pad$1(corner, 150, context);
58007             reveal(pointBox$$1, t('intro.points.reselect'));
58008
58009             context.map().on('move.intro', function() {
58010                 pointBox$$1 = pad$1(corner, 150, context);
58011                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
58012             });
58013         }
58014
58015
58016         function enterReselect(mode) {
58017             if (mode.id !== 'select') return;
58018             context.map().on('move.intro', null);
58019             context.on('enter.intro', null);
58020
58021             setTimeout(function() {
58022                 reveal('.entity-editor-pane',
58023                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
58024                 context.on('exit.intro', deletePoint);
58025             }, 500);
58026         }
58027
58028
58029         function deletePoint() {
58030             context.on('exit.intro', null);
58031             context.on('enter.intro', enterDelete);
58032
58033             var pointBox$$1 = pad$1(corner, 150, context);
58034             reveal(pointBox$$1, t('intro.points.reselect_delete'));
58035
58036             context.map().on('move.intro', function() {
58037                 pointBox$$1 = pad$1(corner, 150, context);
58038                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
58039             });
58040         }
58041
58042
58043         function enterDelete(mode) {
58044             if (mode.id !== 'select') return;
58045             context.map().on('move.intro', null);
58046             context.on('enter.intro', null);
58047             context.on('exit.intro', deletePoint);
58048             context.map().on('move.intro', deletePoint);
58049             context.history().on('change.intro', deleted);
58050
58051             setTimeout(function() {
58052                 var node = select('.radial-menu-item-delete').node();
58053                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
58054                 reveal(pointBox$$1,
58055                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
58056             }, 300);
58057         }
58058
58059
58060         function deleted(changed) {
58061             if (changed.deleted().length) {
58062                 dispatch$$1.call('done');
58063             }
58064         }
58065
58066     };
58067
58068
58069     step.exit = function() {
58070         timeouts.forEach(window.clearTimeout);
58071         context.on('exit.intro', null);
58072         context.on('enter.intro', null);
58073         context.map().on('move.intro', null);
58074         context.history().on('change.intro', null);
58075         select('.preset-search-input')
58076             .on('keyup.intro', null)
58077             .on('keydown.intro', null);
58078     };
58079
58080     return utilRebind(step, dispatch$$1, 'on');
58081 }
58082
58083 function uiIntroArea(context, reveal) {
58084     var dispatch$$1 = dispatch('done'),
58085         timeout$$1;
58086
58087     var step = {
58088         title: 'intro.areas.title'
58089     };
58090
58091
58092     step.enter = function() {
58093         var playground = [-85.63552, 41.94159],
58094             corner = [-85.63565411045074, 41.9417715536927];
58095         context.map().centerZoom(playground, 19);
58096         reveal('button.add-area',
58097             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
58098             { tooltipClass: 'intro-areas-add' });
58099
58100         context.on('enter.intro', addArea);
58101
58102
58103         function addArea(mode) {
58104             if (mode.id !== 'add-area') return;
58105             context.on('enter.intro', drawArea);
58106
58107             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
58108             var pointBox$$1 = pad$1(corner, padding, context);
58109             reveal(pointBox$$1, t('intro.areas.corner'));
58110
58111             context.map().on('move.intro', function() {
58112                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
58113                 pointBox$$1 = pad$1(corner, padding, context);
58114                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
58115             });
58116         }
58117
58118
58119         function drawArea(mode) {
58120             if (mode.id !== 'draw-area') return;
58121             context.on('enter.intro', enterSelect);
58122
58123             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
58124             var pointBox$$1 = pad$1(playground, padding, context);
58125             reveal(pointBox$$1, t('intro.areas.place'));
58126
58127             context.map().on('move.intro', function() {
58128                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
58129                 pointBox$$1 = pad$1(playground, padding, context);
58130                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
58131             });
58132         }
58133
58134
58135         function enterSelect(mode) {
58136             if (mode.id !== 'select') return;
58137             context.map().on('move.intro', null);
58138             context.on('enter.intro', null);
58139
58140             timeout$$1 = setTimeout(function() {
58141                 reveal('.preset-search-input',
58142                     t('intro.areas.search',
58143                     { name: context.presets().item('leisure/playground').name() }));
58144                 select('.preset-search-input').on('keyup.intro', keySearch);
58145             }, 500);
58146         }
58147
58148
58149         function keySearch() {
58150             var first = select('.preset-list-item:first-child');
58151             if (first.classed('preset-leisure-playground')) {
58152                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
58153                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
58154                 select('.preset-search-input').on('keyup.intro', null);
58155             }
58156         }
58157
58158
58159         function selectedPreset() {
58160             reveal('.pane',
58161                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
58162             context.on('exit.intro', function() {
58163                 dispatch$$1.call('done');
58164             });
58165         }
58166     };
58167
58168
58169     step.exit = function() {
58170         window.clearTimeout(timeout$$1);
58171         context.on('enter.intro', null);
58172         context.on('exit.intro', null);
58173         context.history().on('change.intro', null);
58174         context.map().on('move.intro', null);
58175         select('.preset-search-input').on('keyup.intro', null);
58176     };
58177
58178
58179     return utilRebind(step, dispatch$$1, 'on');
58180 }
58181
58182 function uiIntroLine(context, reveal) {
58183     var dispatch$$1 = dispatch('done'),
58184         timeouts = [],
58185         centroid = [-85.62830, 41.95699],
58186         midpoint = [-85.62975395449628, 41.95787501510204],
58187         start = [-85.6297754121684, 41.95805253325314],
58188         intersection = [-85.62974496187628, 41.95742515554585],
58189         targetId = 'w17965351',
58190         drawId = null;
58191
58192
58193     var step = {
58194         title: 'intro.lines.title'
58195     };
58196
58197
58198     function timeout$$1(f, t$$1) {
58199         timeouts.push(window.setTimeout(f, t$$1));
58200     }
58201
58202
58203     function eventCancel() {
58204         event.stopPropagation();
58205         event.preventDefault();
58206     }
58207
58208
58209     step.enter = function() {
58210         context.map().centerZoom(start, 18);
58211         reveal('button.add-line',
58212             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
58213             { tooltipClass: 'intro-lines-add' });
58214
58215         context.on('enter.intro', addLine);
58216
58217
58218         function addLine(mode) {
58219             if (mode.id !== 'add-line') return;
58220             drawId = null;
58221             context.on('enter.intro', drawLine);
58222
58223             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
58224             var pointBox$$1 = pad$1(start, padding, context);
58225             reveal(pointBox$$1, t('intro.lines.start'));
58226
58227             context.map().on('move.intro', function() {
58228                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
58229                 pointBox$$1 = pad$1(start, padding, context);
58230                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
58231             });
58232         }
58233
58234
58235         function drawLine(mode) {
58236             if (mode.id !== 'draw-line') return;
58237             drawId = mode.selectedIDs()[0];
58238             context.history().on('change.intro', checkIntersection);
58239             context.on('enter.intro', retry);
58240
58241             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
58242             var pointBox$$1 = pad$1(midpoint, padding, context);
58243             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
58244
58245             context.map().on('move.intro', function() {
58246                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
58247                 pointBox$$1 = pad$1(midpoint, padding, context);
58248                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
58249             });
58250         }
58251
58252
58253         // ended line before creating intersection
58254         function retry(mode) {
58255             if (mode.id !== 'select') return;
58256             context.history().on('change.intro', null);
58257             var pointBox$$1 = pad$1(intersection, 30, context);
58258             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
58259             select(window).on('mousedown.intro', eventCancel, true);
58260
58261             timeout$$1(step.restart, 3000);
58262         }
58263
58264
58265         function checkIntersection() {
58266
58267             function joinedTargetWay() {
58268                 var drawEntity = drawId && context.hasEntity(drawId);
58269                 if (!drawEntity) {
58270                     step.restart();
58271                     return false;
58272                 }
58273
58274                 var drawNodes = context.graph().childNodes(drawEntity);
58275                 return lodash.some(drawNodes, function(node) {
58276                     return lodash.some(context.graph().parentWays(node), function(parent) {
58277                         return parent.id === targetId;
58278                     });
58279                 });
58280             }
58281
58282             if (joinedTargetWay()) {
58283                 context.history().on('change.intro', null);
58284                 context.on('enter.intro', enterSelect);
58285
58286                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
58287                 var pointBox$$1 = pad$1(centroid, padding, context);
58288                 reveal(pointBox$$1, t('intro.lines.finish'));
58289
58290                 context.map().on('move.intro', function() {
58291                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
58292                     pointBox$$1 = pad$1(centroid, padding, context);
58293                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
58294                 });
58295             }
58296         }
58297
58298
58299         function enterSelect(mode) {
58300             if (mode.id !== 'select') return;
58301             context.map().on('move.intro', null);
58302             context.on('enter.intro', null);
58303             select('#curtain').style('pointer-events', 'all');
58304             presetCategory();
58305         }
58306
58307
58308         function presetCategory() {
58309             timeout$$1(function() {
58310                 select('#curtain').style('pointer-events', 'none');
58311                 var road = select('.preset-category-road .preset-list-button');
58312                 reveal(road.node(), t('intro.lines.road'));
58313                 utilBindOnce(road, 'click.intro', roadCategory);
58314             }, 500);
58315         }
58316
58317
58318         function roadCategory() {
58319             timeout$$1(function() {
58320                 var grid = select('.subgrid');
58321                 reveal(grid.node(), t('intro.lines.residential'));
58322                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
58323                     'click.intro', retryPreset);
58324                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
58325                     'click.intro', roadDetails);
58326             }, 500);
58327         }
58328
58329
58330         // selected wrong road type
58331         function retryPreset() {
58332             timeout$$1(function() {
58333                 var preset = select('.entity-editor-pane .preset-list-button');
58334                 reveal(preset.node(), t('intro.lines.wrong_preset'));
58335                 utilBindOnce(preset, 'click.intro', presetCategory);
58336             }, 500);
58337         }
58338
58339
58340         function roadDetails() {
58341             reveal('.pane',
58342                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
58343             context.on('exit.intro', function() {
58344                 dispatch$$1.call('done');
58345             });
58346         }
58347     };
58348
58349
58350     step.restart = function() {
58351         step.exit();
58352         step.enter();
58353     };
58354
58355
58356     step.exit = function() {
58357         select(window).on('mousedown.intro', null, true);
58358         select('#curtain').style('pointer-events', 'none');
58359         timeouts.forEach(window.clearTimeout);
58360         context.on('enter.intro', null);
58361         context.on('exit.intro', null);
58362         context.map().on('move.intro', null);
58363         context.history().on('change.intro', null);
58364         if (drawId) {
58365             context.replace(actionDeleteMultiple([drawId]));
58366             drawId = null;
58367         }
58368     };
58369
58370     return utilRebind(step, dispatch$$1, 'on');
58371 }
58372
58373 function uiIntroStartEditing(context, reveal) {
58374     var dispatch$$1 = dispatch('done', 'startEditing'),
58375         modalSelection,
58376         timeouts = [];
58377
58378     var step = {
58379         title: 'intro.startediting.title'
58380     };
58381
58382
58383     function timeout$$1(f, t$$1) {
58384         timeouts.push(window.setTimeout(f, t$$1));
58385     }
58386
58387
58388     step.enter = function() {
58389         reveal('.map-control.help-control',
58390             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
58391
58392         timeout$$1(function() {
58393             reveal('#bar button.save', t('intro.startediting.save'));
58394         }, 5000);
58395
58396         timeout$$1(function() {
58397             reveal('#surface');
58398         }, 10000);
58399
58400         timeout$$1(function() {
58401             modalSelection = uiModal(context.container());
58402
58403             modalSelection.select('.modal')
58404                 .attr('class', 'modal-splash modal col6');
58405
58406             modalSelection.selectAll('.close').remove();
58407
58408             var startbutton = modalSelection.select('.content')
58409                 .attr('class', 'fillL')
58410                 .append('button')
58411                     .attr('class', 'modal-section huge-modal-button')
58412                     .on('click', function() {
58413                         modalSelection.remove();
58414                     });
58415
58416                 startbutton
58417                     .append('div')
58418                     .attr('class','illustration');
58419
58420                 startbutton
58421                     .append('h2')
58422                     .text(t('intro.startediting.start'));
58423
58424             dispatch$$1.call('startEditing');
58425         }, 10500);
58426     };
58427
58428
58429     step.exit = function() {
58430         if (modalSelection) { modalSelection.remove(); }
58431         timeouts.forEach(window.clearTimeout);
58432     };
58433
58434
58435     return utilRebind(step, dispatch$$1, 'on');
58436 }
58437
58438 var sampleIntros = {
58439     navigation: uiIntroNavigation,
58440     point: uiIntroPoint,
58441     area: uiIntroArea,
58442     line: uiIntroLine,
58443     startEditing: uiIntroStartEditing
58444 };
58445
58446
58447 function uiIntro(context) {
58448     var step;
58449
58450     function localizedName(id) {
58451         var features = {
58452             n2140018997: 'city_hall',
58453             n367813436: 'fire_department',
58454             w203988286: 'memory_isle_park',
58455             w203972937: 'riverwalk_trail',
58456             w203972938: 'riverwalk_trail',
58457             w203972940: 'riverwalk_trail',
58458             w41785752: 'w_michigan_ave',
58459             w134150789: 'w_michigan_ave',
58460             w134150795: 'w_michigan_ave',
58461             w134150800: 'w_michigan_ave',
58462             w134150811: 'w_michigan_ave',
58463             w134150802: 'e_michigan_ave',
58464             w134150836: 'e_michigan_ave',
58465             w41074896: 'e_michigan_ave',
58466             w17965834: 'spring_st',
58467             w203986457: 'scidmore_park',
58468             w203049587: 'petting_zoo',
58469             w17967397: 'n_andrews_st',
58470             w17967315: 's_andrews_st',
58471             w17967326: 'n_constantine_st',
58472             w17966400: 's_constantine_st',
58473             w170848823: 'rocky_river',
58474             w170848824: 'rocky_river',
58475             w170848331: 'rocky_river',
58476             w17967752: 'railroad_dr',
58477             w17965998: 'conrail_rr',
58478             w134150845: 'conrail_rr',
58479             w170989131: 'st_joseph_river',
58480             w143497377: 'n_main_st',
58481             w134150801: 's_main_st',
58482             w134150830: 's_main_st',
58483             w17966462: 's_main_st',
58484             w17967734: 'water_st',
58485             w17964996: 'foster_st',
58486             w170848330: 'portage_river',
58487             w17965351: 'flower_st',
58488             w17965502: 'elm_st',
58489             w17965402: 'walnut_st',
58490             w17964793: 'morris_ave',
58491             w17967444: 'east_st',
58492             w17966984: 'portage_ave'
58493         };
58494
58495         return features[id] && t('intro.graph.' + features[id]);
58496     }
58497
58498
58499     var introGraph = {};
58500
58501     for (var key in dataIntroGraph) {
58502         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
58503         var name = localizedName(key);
58504         if (name) {
58505             introGraph[key].tags.name = name;
58506         }
58507     }
58508
58509
58510     function intro(selection$$1) {
58511         context.enter(modeBrowse(context));
58512
58513         // Save current map state
58514         var history = context.history().toJSON(),
58515             hash = window.location.hash,
58516             center = context.map().center(),
58517             zoom$$1 = context.map().zoom(),
58518             background = context.background().baseLayerSource(),
58519             opacity = selectAll('#map .layer-background').style('opacity'),
58520             loadedTiles = context.connection().loadedTiles(),
58521             baseEntities = context.history().graph().base().entities;
58522
58523         // Block saving
58524         context.inIntro(true);
58525
58526         // Load semi-real data used in intro
58527         context.connection().toggle(false).reset();
58528         context.history().reset();
58529
58530         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
58531         context.background().bing();
58532
58533         selectAll('#map .layer-background').style('opacity', 1);
58534
58535         var curtain = d3curtain();
58536         selection$$1.call(curtain);
58537
58538
58539         function reveal(box, text$$1, options) {
58540             options = options || {};
58541             curtain.reveal(box,
58542                 text$$1 || '',
58543                 options.tooltipClass || '',
58544                 options.duration
58545             );
58546         }
58547
58548         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
58549             var s = sampleIntros[step](context, reveal)
58550                 .on('done', function() {
58551                     entered.filter(function(d) {
58552                         return d.title === s.title;
58553                     }).classed('finished', true);
58554                     enter(steps[i + 1]);
58555                 });
58556             return s;
58557         });
58558
58559         steps[steps.length - 1].on('startEditing', function() {
58560             curtain.remove();
58561             navwrap.remove();
58562             selectAll('#map .layer-background').style('opacity', opacity);
58563             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
58564             context.history().reset().merge(values(baseEntities));
58565             context.background().baseLayerSource(background);
58566             if (history) context.history().fromJSON(history, false);
58567             context.map().centerZoom(center, zoom$$1);
58568             window.location.replace(hash);
58569             context.inIntro(false);
58570         });
58571
58572         var navwrap = selection$$1
58573             .append('div')
58574             .attr('class', 'intro-nav-wrap fillD');
58575
58576         var buttonwrap = navwrap
58577             .append('div')
58578             .attr('class', 'joined')
58579             .selectAll('button.step');
58580
58581         var entered = buttonwrap
58582             .data(steps)
58583             .enter()
58584             .append('button')
58585             .attr('class', 'step')
58586             .on('click', enter);
58587
58588         entered
58589             .append('label')
58590             .text(function(d) { return t(d.title); });
58591
58592         entered
58593             .append('span')
58594             .attr('class', 'status')
58595             .text(' - ' + t('intro.done'));
58596
58597         enter(steps[0]);
58598
58599
58600         function enter(newStep) {
58601             if (step) { step.exit(); }
58602
58603             context.enter(modeBrowse(context));
58604
58605             step = newStep;
58606             step.enter();
58607
58608             entered.classed('active', function(d) {
58609                 return d.title === step.title;
58610             });
58611         }
58612
58613     }
58614
58615
58616     return intro;
58617 }
58618
58619 function uiHelp(context) {
58620     var key = 'H';
58621
58622     var docKeys = [
58623         'help.help',
58624         'help.editing_saving',
58625         'help.roads',
58626         'help.gps',
58627         'help.imagery',
58628         'help.addresses',
58629         'help.inspector',
58630         'help.buildings',
58631         'help.relations'];
58632
58633     var docs = docKeys.map(function(key) {
58634         var text$$1 = t(key);
58635         return {
58636             title: text$$1.split('\n')[0].replace('#', '').trim(),
58637             html: marked(text$$1.split('\n').slice(1).join('\n'))
58638         };
58639     });
58640
58641
58642     function help(selection$$1) {
58643
58644         function hide() {
58645             setVisible(false);
58646         }
58647
58648
58649         function toggle() {
58650             if (event) event.preventDefault();
58651             tooltipBehavior.hide(button);
58652             setVisible(!button.classed('active'));
58653         }
58654
58655
58656         function setVisible(show) {
58657             if (show !== shown) {
58658                 button.classed('active', show);
58659                 shown = show;
58660
58661                 if (show) {
58662                     selection$$1.on('mousedown.help-inside', function() {
58663                         return event.stopPropagation();
58664                     });
58665                     pane.style('display', 'block')
58666                         .style('right', '-500px')
58667                         .transition()
58668                         .duration(200)
58669                         .style('right', '0px');
58670                 } else {
58671                     pane.style('right', '0px')
58672                         .transition()
58673                         .duration(200)
58674                         .style('right', '-500px')
58675                         .on('end', function() {
58676                             select(this).style('display', 'none');
58677                         });
58678                     selection$$1.on('mousedown.help-inside', null);
58679                 }
58680             }
58681         }
58682
58683
58684         function clickHelp(d, i) {
58685             var rtl = (textDirection === 'rtl');
58686             pane.property('scrollTop', 0);
58687             doctitle.html(d.title);
58688
58689             body.html(d.html);
58690             body.selectAll('a')
58691                 .attr('target', '_blank');
58692             menuItems.classed('selected', function(m) {
58693                 return m.title === d.title;
58694             });
58695
58696             nav.html('');
58697             if (rtl) {
58698                 nav.call(drawNext).call(drawPrevious);
58699             } else {
58700                 nav.call(drawPrevious).call(drawNext);
58701             }
58702
58703
58704             function drawNext(selection$$1) {
58705                 if (i < docs.length - 1) {
58706                     var nextLink = selection$$1
58707                         .append('a')
58708                         .attr('class', 'next')
58709                         .on('click', function() {
58710                             clickHelp(docs[i + 1], i + 1);
58711                         });
58712
58713                     nextLink
58714                         .append('span')
58715                         .text(docs[i + 1].title)
58716                         .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
58717                 }
58718             }
58719
58720
58721             function drawPrevious(selection$$1) {
58722                 if (i > 0) {
58723                     var prevLink = selection$$1
58724                         .append('a')
58725                         .attr('class', 'previous')
58726                         .on('click', function() {
58727                             clickHelp(docs[i - 1], i - 1);
58728                         });
58729
58730                     prevLink
58731                         .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
58732                         .append('span')
58733                         .text(docs[i - 1].title);
58734                 }
58735             }
58736         }
58737
58738
58739         function clickWalkthrough() {
58740             select(document.body).call(uiIntro(context));
58741             setVisible(false);
58742         }
58743
58744
58745         var pane = selection$$1.append('div')
58746                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
58747             tooltipBehavior = tooltip()
58748                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58749                 .html(true)
58750                 .title(uiTooltipHtml(t('help.title'), key)),
58751             button = selection$$1.append('button')
58752                 .attr('tabindex', -1)
58753                 .on('click', toggle)
58754                 .call(svgIcon('#icon-help', 'light'))
58755                 .call(tooltipBehavior),
58756             shown = false;
58757
58758
58759         var toc = pane.append('ul')
58760             .attr('class', 'toc');
58761
58762         var menuItems = toc.selectAll('li')
58763             .data(docs)
58764             .enter()
58765             .append('li')
58766             .append('a')
58767             .html(function(d) { return d.title; })
58768             .on('click', clickHelp);
58769
58770         toc.append('li')
58771             .attr('class','walkthrough')
58772             .append('a')
58773             .text(t('splash.walkthrough'))
58774             .on('click', clickWalkthrough);
58775
58776         var content = pane.append('div')
58777             .attr('class', 'left-content');
58778
58779         var doctitle = content.append('h2')
58780             .text(t('help.title'));
58781
58782         var body = content.append('div')
58783             .attr('class', 'body');
58784
58785         var nav = content.append('div')
58786             .attr('class', 'nav');
58787
58788         clickHelp(docs[0], 0);
58789
58790         var keybinding = d3keybinding('help')
58791             .on(key, toggle)
58792             .on('B', hide)
58793             .on('F', hide);
58794
58795         select(document)
58796             .call(keybinding);
58797
58798         context.surface().on('mousedown.help-outside', hide);
58799         context.container().on('mousedown.help-outside', hide);
58800     }
58801
58802     return help;
58803 }
58804
58805 function uiInfo(context) {
58806     var key = uiCmd('⌘I'),
58807         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58808         isHidden = true;
58809
58810
58811     function info(selection$$1) {
58812
58813         function radiansToMeters(r) {
58814             // using WGS84 authalic radius (6371007.1809 m)
58815             return r * 6371007.1809;
58816         }
58817
58818         function steradiansToSqmeters(r) {
58819             // http://gis.stackexchange.com/a/124857/40446
58820             return r / (4 * Math.PI) * 510065621724000;
58821         }
58822
58823
58824         function toLineString(feature) {
58825             if (feature.type === 'LineString') return feature;
58826
58827             var result = { type: 'LineString', coordinates: [] };
58828             if (feature.type === 'Polygon') {
58829                 result.coordinates = feature.coordinates[0];
58830             } else if (feature.type === 'MultiPolygon') {
58831                 result.coordinates = feature.coordinates[0][0];
58832             }
58833
58834             return result;
58835         }
58836
58837
58838         function displayLength(m) {
58839             var d = m * (isImperial ? 3.28084 : 1),
58840                 p, unit;
58841
58842             if (isImperial) {
58843                 if (d >= 5280) {
58844                     d /= 5280;
58845                     unit = 'mi';
58846                 } else {
58847                     unit = 'ft';
58848                 }
58849             } else {
58850                 if (d >= 1000) {
58851                     d /= 1000;
58852                     unit = 'km';
58853                 } else {
58854                     unit = 'm';
58855                 }
58856             }
58857
58858             // drop unnecessary precision
58859             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
58860
58861             return String(d.toFixed(p)) + ' ' + unit;
58862         }
58863
58864
58865         function displayArea(m2) {
58866             var d = m2 * (isImperial ? 10.7639111056 : 1),
58867                 d1, d2, p1, p2, unit1, unit2;
58868
58869             if (isImperial) {
58870                 if (d >= 6969600) {     // > 0.25mi² show mi²
58871                     d1 = d / 27878400;
58872                     unit1 = 'mi²';
58873                 } else {
58874                     d1 = d;
58875                     unit1 = 'ft²';
58876                 }
58877
58878                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
58879                     d2 = d / 43560;
58880                     unit2 = 'ac';
58881                 }
58882
58883             } else {
58884                 if (d >= 250000) {    // > 0.25km² show km²
58885                     d1 = d / 1000000;
58886                     unit1 = 'km²';
58887                 } else {
58888                     d1 = d;
58889                     unit1 = 'm²';
58890                 }
58891
58892                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
58893                     d2 = d / 10000;
58894                     unit2 = 'ha';
58895                 }
58896             }
58897
58898             // drop unnecessary precision
58899             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
58900             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
58901
58902             return String(d1.toFixed(p1)) + ' ' + unit1 +
58903                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
58904         }
58905
58906
58907         function redraw() {
58908             if (isHidden) return;
58909
58910             var resolver = context.graph(),
58911                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
58912                 singular = selected.length === 1 ? selected[0] : null,
58913                 extent$$1 = geoExtent$$1(),
58914                 entity;
58915
58916             wrap.html('');
58917             wrap.append('h4')
58918                 .attr('class', 'infobox-heading fillD')
58919                 .text(singular || t('infobox.selected', { n: selected.length }));
58920
58921             if (!selected.length) return;
58922
58923             var center;
58924             for (var i = 0; i < selected.length; i++) {
58925                 entity = context.entity(selected[i]);
58926                 extent$$1._extend(entity.extent(resolver));
58927             }
58928             center = extent$$1.center();
58929
58930
58931             var list = wrap.append('ul');
58932
58933             // multiple features, just display extent center..
58934             if (!singular) {
58935                 list.append('li')
58936                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58937                 return;
58938             }
58939
58940             // single feature, display details..
58941             if (!entity) return;
58942             var geometry = entity.geometry(resolver);
58943
58944             if (geometry === 'line' || geometry === 'area') {
58945                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
58946                     feature = entity.asGeoJSON(resolver),
58947                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
58948                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
58949                     centroid = d3GeoCentroid(feature);
58950
58951                 list.append('li')
58952                     .text(t('infobox.geometry') + ': ' +
58953                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
58954
58955                 if (closed) {
58956                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
58957                     list.append('li')
58958                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
58959                 }
58960
58961                 list.append('li')
58962                     .text(lengthLabel + ': ' + displayLength(length));
58963
58964                 list.append('li')
58965                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
58966
58967
58968                 var toggle  = isImperial ? 'imperial' : 'metric';
58969                 wrap.append('a')
58970                     .text(t('infobox.' + toggle))
58971                     .attr('href', '#')
58972                     .attr('class', 'button')
58973                     .on('click', function() {
58974                         event.preventDefault();
58975                         isImperial = !isImperial;
58976                         redraw();
58977                     });
58978
58979             } else {
58980                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
58981
58982                 list.append('li')
58983                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
58984
58985                 list.append('li')
58986                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58987             }
58988         }
58989
58990
58991         function toggle() {
58992             if (event) {
58993                 event.preventDefault();
58994             }
58995
58996             isHidden = !isHidden;
58997
58998             if (isHidden) {
58999                 wrap
59000                     .style('display', 'block')
59001                     .style('opacity', 1)
59002                     .transition()
59003                     .duration(200)
59004                     .style('opacity', 0)
59005                     .on('end', function() {
59006                         select(this).style('display', 'none');
59007                     });
59008             } else {
59009                 wrap
59010                     .style('display', 'block')
59011                     .style('opacity', 0)
59012                     .transition()
59013                     .duration(200)
59014                     .style('opacity', 1)
59015                     .on('end', function() {
59016                         redraw();
59017                     });
59018             }
59019         }
59020
59021
59022         var wrap = selection$$1.selectAll('.infobox')
59023             .data([0]);
59024
59025         wrap = wrap.enter()
59026             .append('div')
59027             .attr('class', 'infobox fillD2')
59028             .style('display', (isHidden ? 'none' : 'block'))
59029             .merge(wrap);
59030
59031         context.map()
59032             .on('drawn.info', redraw);
59033
59034         redraw();
59035
59036         var keybinding = d3keybinding('info')
59037             .on(key, toggle);
59038
59039         select(document)
59040             .call(keybinding);
59041     }
59042
59043     return info;
59044 }
59045
59046 function uiMapData(context) {
59047     var key = 'F',
59048         features = context.features().keys(),
59049         layers = context.layers(),
59050         fills = ['wireframe', 'partial', 'full'],
59051         fillDefault = context.storage('area-fill') || 'partial',
59052         fillSelected = fillDefault;
59053
59054
59055     function map_data(selection$$1) {
59056
59057         function showsFeature(d) {
59058             return context.features().enabled(d);
59059         }
59060
59061
59062         function autoHiddenFeature(d) {
59063             return context.features().autoHidden(d);
59064         }
59065
59066
59067         function clickFeature(d) {
59068             context.features().toggle(d);
59069             update();
59070         }
59071
59072
59073         function showsFill(d) {
59074             return fillSelected === d;
59075         }
59076
59077
59078         function setFill(d) {
59079             lodash.each(fills, function(opt) {
59080                 context.surface().classed('fill-' + opt, Boolean(opt === d));
59081             });
59082
59083             fillSelected = d;
59084             if (d !== 'wireframe') {
59085                 fillDefault = d;
59086                 context.storage('area-fill', d);
59087             }
59088             update();
59089         }
59090
59091
59092         function showsLayer(which) {
59093             var layer = layers.layer(which);
59094             if (layer) {
59095                 return layer.enabled();
59096             }
59097             return false;
59098         }
59099
59100
59101         function setLayer(which, enabled) {
59102             var layer = layers.layer(which);
59103             if (layer) {
59104                 layer.enabled(enabled);
59105                 update();
59106             }
59107         }
59108
59109
59110         function toggleLayer(which) {
59111             setLayer(which, !showsLayer(which));
59112         }
59113
59114
59115         function clickGpx() {
59116             toggleLayer('gpx');
59117         }
59118
59119
59120         function clickMapillaryImages() {
59121             toggleLayer('mapillary-images');
59122             if (!showsLayer('mapillary-images')) {
59123                 setLayer('mapillary-signs', false);
59124             }
59125         }
59126
59127
59128         function clickMapillarySigns() {
59129             toggleLayer('mapillary-signs');
59130         }
59131
59132
59133         function drawMapillaryItems(selection$$1) {
59134             var mapillaryImages = layers.layer('mapillary-images'),
59135                 mapillarySigns = layers.layer('mapillary-signs'),
59136                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
59137                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
59138                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
59139                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
59140
59141             var mapillaryList = selection$$1
59142                 .selectAll('.layer-list-mapillary')
59143                 .data([0]);
59144
59145             mapillaryList = mapillaryList.enter()
59146                 .append('ul')
59147                 .attr('class', 'layer-list layer-list-mapillary')
59148                 .merge(mapillaryList);
59149
59150
59151             var mapillaryImageLayerItem = mapillaryList
59152                 .selectAll('.list-item-mapillary-images')
59153                 .data(supportsMapillaryImages ? [0] : []);
59154
59155             mapillaryImageLayerItem.exit()
59156                 .remove();
59157
59158             var enterImages = mapillaryImageLayerItem.enter()
59159                 .append('li')
59160                 .attr('class', 'list-item-mapillary-images');
59161
59162             var labelImages = enterImages
59163                 .append('label')
59164                 .call(tooltip()
59165                     .title(t('mapillary_images.tooltip'))
59166                     .placement('top'));
59167
59168             labelImages
59169                 .append('input')
59170                 .attr('type', 'checkbox')
59171                 .on('change', clickMapillaryImages);
59172
59173             labelImages
59174                 .append('span')
59175                 .text(t('mapillary_images.title'));
59176
59177
59178             var mapillarySignLayerItem = mapillaryList
59179                 .selectAll('.list-item-mapillary-signs')
59180                 .data(supportsMapillarySigns ? [0] : []);
59181
59182             mapillarySignLayerItem.exit()
59183                 .remove();
59184
59185             var enterSigns = mapillarySignLayerItem.enter()
59186                 .append('li')
59187                 .attr('class', 'list-item-mapillary-signs');
59188
59189             var labelSigns = enterSigns
59190                 .append('label')
59191                 .call(tooltip()
59192                     .title(t('mapillary_signs.tooltip'))
59193                     .placement('top'));
59194
59195             labelSigns
59196                 .append('input')
59197                 .attr('type', 'checkbox')
59198                 .on('change', clickMapillarySigns);
59199
59200             labelSigns
59201                 .append('span')
59202                 .text(t('mapillary_signs.title'));
59203
59204
59205             // Updates
59206             mapillaryImageLayerItem = mapillaryImageLayerItem
59207                 .merge(enterImages);
59208
59209             mapillaryImageLayerItem
59210                 .classed('active', showsMapillaryImages)
59211                 .selectAll('input')
59212                 .property('checked', showsMapillaryImages);
59213
59214
59215             mapillarySignLayerItem = mapillarySignLayerItem
59216                 .merge(enterSigns);
59217
59218             mapillarySignLayerItem
59219                 .classed('active', showsMapillarySigns)
59220                 .selectAll('input')
59221                 .property('disabled', !showsMapillaryImages)
59222                 .property('checked', showsMapillarySigns);
59223
59224             mapillarySignLayerItem
59225                 .selectAll('label')
59226                 .classed('deemphasize', !showsMapillaryImages);
59227         }
59228
59229
59230         function drawGpxItem(selection$$1) {
59231             var gpx = layers.layer('gpx'),
59232                 hasGpx = gpx && gpx.hasGpx(),
59233                 showsGpx = hasGpx && gpx.enabled();
59234
59235             var gpxLayerItem = selection$$1
59236                 .selectAll('.layer-list-gpx')
59237                 .data(gpx ? [0] : []);
59238
59239             // Exit
59240             gpxLayerItem.exit()
59241                 .remove();
59242
59243             // Enter
59244             var enter = gpxLayerItem.enter()
59245                 .append('ul')
59246                 .attr('class', 'layer-list layer-list-gpx')
59247                 .append('li')
59248                 .classed('list-item-gpx', true);
59249
59250             enter
59251                 .append('button')
59252                 .attr('class', 'list-item-gpx-extent')
59253                 .call(tooltip()
59254                     .title(t('gpx.zoom'))
59255                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59256                 .on('click', function() {
59257                     event.preventDefault();
59258                     event.stopPropagation();
59259                     gpx.fitZoom();
59260                 })
59261                 .call(svgIcon('#icon-search'));
59262
59263             enter
59264                 .append('button')
59265                 .attr('class', 'list-item-gpx-browse')
59266                 .call(tooltip()
59267                     .title(t('gpx.browse'))
59268                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59269                 .on('click', function() {
59270                     select(document.createElement('input'))
59271                         .attr('type', 'file')
59272                         .on('change', function() {
59273                             gpx.files(event.target.files);
59274                         })
59275                         .node().click();
59276                 })
59277                 .call(svgIcon('#icon-geolocate'));
59278
59279             var labelGpx = enter
59280                 .append('label')
59281                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
59282
59283             labelGpx
59284                 .append('input')
59285                 .attr('type', 'checkbox')
59286                 .on('change', clickGpx);
59287
59288             labelGpx
59289                 .append('span')
59290                 .text(t('gpx.local_layer'));
59291
59292
59293             // Update
59294             gpxLayerItem = gpxLayerItem
59295                 .merge(enter);
59296
59297             gpxLayerItem
59298                 .classed('active', showsGpx)
59299                 .selectAll('input')
59300                 .property('disabled', !hasGpx)
59301                 .property('checked', showsGpx);
59302
59303             gpxLayerItem
59304                 .selectAll('label')
59305                 .classed('deemphasize', !hasGpx);
59306         }
59307
59308
59309         function drawList(selection$$1, data, type, name, change, active$$1) {
59310             var items = selection$$1.selectAll('li')
59311                 .data(data);
59312
59313             // Exit
59314             items.exit()
59315                 .remove();
59316
59317             // Enter
59318             var enter = items.enter()
59319                 .append('li')
59320                 .attr('class', 'layer')
59321                 .call(tooltip()
59322                     .html(true)
59323                     .title(function(d) {
59324                         var tip = t(name + '.' + d + '.tooltip'),
59325                             key = (d === 'wireframe' ? 'W' : null);
59326
59327                         if (name === 'feature' && autoHiddenFeature(d)) {
59328                             tip += '<div>' + t('map_data.autohidden') + '</div>';
59329                         }
59330                         return uiTooltipHtml(tip, key);
59331                     })
59332                     .placement('top')
59333                 );
59334
59335             var label = enter
59336                 .append('label');
59337
59338             label
59339                 .append('input')
59340                 .attr('type', type)
59341                 .attr('name', name)
59342                 .on('change', change);
59343
59344             label
59345                 .append('span')
59346                 .text(function(d) { return t(name + '.' + d + '.description'); });
59347
59348             // Update
59349             items = items
59350                 .merge(enter);
59351
59352             items
59353                 .classed('active', active$$1)
59354                 .selectAll('input')
59355                 .property('checked', active$$1)
59356                 .property('indeterminate', function(d) {
59357                     return (name === 'feature' && autoHiddenFeature(d));
59358                 });
59359         }
59360
59361
59362         function update() {
59363             dataLayerContainer.call(drawMapillaryItems);
59364             dataLayerContainer.call(drawGpxItem);
59365
59366             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
59367             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
59368         }
59369
59370
59371         function hidePanel() {
59372             setVisible(false);
59373         }
59374
59375
59376         function togglePanel() {
59377             if (event) event.preventDefault();
59378             tooltipBehavior.hide(button);
59379             setVisible(!button.classed('active'));
59380         }
59381
59382
59383         function toggleWireframe() {
59384             if (event) {
59385                 event.preventDefault();
59386                 event.stopPropagation();
59387             }
59388             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
59389             context.map().pan([0,0]);  // trigger a redraw
59390         }
59391
59392
59393         function setVisible(show) {
59394             if (show !== shown) {
59395                 button.classed('active', show);
59396                 shown = show;
59397
59398                 if (show) {
59399                     update();
59400                     selection$$1.on('mousedown.map_data-inside', function() {
59401                         return event.stopPropagation();
59402                     });
59403                     content.style('display', 'block')
59404                         .style('right', '-300px')
59405                         .transition()
59406                         .duration(200)
59407                         .style('right', '0px');
59408                 } else {
59409                     content.style('display', 'block')
59410                         .style('right', '0px')
59411                         .transition()
59412                         .duration(200)
59413                         .style('right', '-300px')
59414                         .on('end', function() {
59415                             select(this).style('display', 'none');
59416                         });
59417                     selection$$1.on('mousedown.map_data-inside', null);
59418                 }
59419             }
59420         }
59421
59422
59423         var content = selection$$1
59424                 .append('div')
59425                 .attr('class', 'fillL map-overlay col3 content hide'),
59426             tooltipBehavior = tooltip()
59427                 .placement((textDirection === 'rtl') ? 'right' : 'left')
59428                 .html(true)
59429                 .title(uiTooltipHtml(t('map_data.description'), key)),
59430             button = selection$$1
59431                 .append('button')
59432                 .attr('tabindex', -1)
59433                 .on('click', togglePanel)
59434                 .call(svgIcon('#icon-data', 'light'))
59435                 .call(tooltipBehavior),
59436             shown = false;
59437
59438         content
59439             .append('h4')
59440             .text(t('map_data.title'));
59441
59442
59443         // data layers
59444         content
59445             .append('a')
59446             .text(t('map_data.data_layers'))
59447             .attr('href', '#')
59448             .classed('hide-toggle', true)
59449             .classed('expanded', true)
59450             .on('click', function() {
59451                 var exp = select(this).classed('expanded');
59452                 dataLayerContainer.style('display', exp ? 'none' : 'block');
59453                 select(this).classed('expanded', !exp);
59454                 event.preventDefault();
59455             });
59456
59457         var dataLayerContainer = content
59458             .append('div')
59459             .attr('class', 'data-data-layers')
59460             .style('display', 'block');
59461
59462
59463         // area fills
59464         content
59465             .append('a')
59466             .text(t('map_data.fill_area'))
59467             .attr('href', '#')
59468             .classed('hide-toggle', true)
59469             .classed('expanded', false)
59470             .on('click', function() {
59471                 var exp = select(this).classed('expanded');
59472                 fillContainer.style('display', exp ? 'none' : 'block');
59473                 select(this).classed('expanded', !exp);
59474                 event.preventDefault();
59475             });
59476
59477         var fillContainer = content
59478             .append('div')
59479             .attr('class', 'data-area-fills')
59480             .style('display', 'none');
59481
59482         var fillList = fillContainer
59483             .append('ul')
59484             .attr('class', 'layer-list layer-fill-list');
59485
59486
59487         // feature filters
59488         content
59489             .append('a')
59490             .text(t('map_data.map_features'))
59491             .attr('href', '#')
59492             .classed('hide-toggle', true)
59493             .classed('expanded', false)
59494             .on('click', function() {
59495                 var exp = select(this).classed('expanded');
59496                 featureContainer.style('display', exp ? 'none' : 'block');
59497                 select(this).classed('expanded', !exp);
59498                 event.preventDefault();
59499             });
59500
59501         var featureContainer = content
59502             .append('div')
59503             .attr('class', 'data-feature-filters')
59504             .style('display', 'none');
59505
59506         var featureList = featureContainer
59507             .append('ul')
59508             .attr('class', 'layer-list layer-feature-list');
59509
59510
59511         context.features()
59512             .on('change.map_data-update', update);
59513
59514         setFill(fillDefault);
59515
59516         var keybinding = d3keybinding('features')
59517             .on(key, togglePanel)
59518             .on('W', toggleWireframe)
59519             .on('B', hidePanel)
59520             .on('H', hidePanel);
59521
59522         select(document)
59523             .call(keybinding);
59524
59525         context.surface().on('mousedown.map_data-outside', hidePanel);
59526         context.container().on('mousedown.map_data-outside', hidePanel);
59527     }
59528
59529
59530     return map_data;
59531 }
59532
59533 function uiModes(context) {
59534     var modes = [
59535         modeAddPoint$$1(context),
59536         modeAddLine$$1(context),
59537         modeAddArea$$1(context)
59538     ];
59539
59540
59541     function editable() {
59542         return context.editable() && context.mode().id !== 'save';
59543     }
59544
59545
59546     return function(selection$$1) {
59547         var buttons = selection$$1.selectAll('button.add-button')
59548             .data(modes);
59549
59550         buttons = buttons.enter()
59551             .append('button')
59552             .attr('tabindex', -1)
59553             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
59554             .on('click.mode-buttons', function(mode) {
59555                 if (mode.id === context.mode().id) {
59556                     context.enter(modeBrowse(context));
59557                 } else {
59558                     context.enter(mode);
59559                 }
59560             })
59561             .call(tooltip()
59562                 .placement('bottom')
59563                 .html(true)
59564                 .title(function(mode) {
59565                     return uiTooltipHtml(mode.description, mode.key);
59566                 })
59567             );
59568
59569         context.map()
59570             .on('move.modes', lodash.debounce(update, 500));
59571
59572         context
59573             .on('enter.modes', update);
59574
59575         buttons
59576             .each(function(d) {
59577                 select(this)
59578                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
59579             });
59580
59581         buttons
59582             .append('span')
59583             .attr('class', 'label')
59584             .text(function(mode) { return mode.title; });
59585
59586         context
59587             .on('enter.editor', function(entered) {
59588                 selection$$1.selectAll('button.add-button')
59589                     .classed('active', function(mode) { return entered.button === mode.button; });
59590                 context.container()
59591                     .classed('mode-' + entered.id, true);
59592             });
59593
59594         context
59595             .on('exit.editor', function(exited) {
59596                 context.container()
59597                     .classed('mode-' + exited.id, false);
59598             });
59599
59600         var keybinding = d3keybinding('mode-buttons');
59601
59602         modes.forEach(function(m) {
59603             keybinding.on(m.key, function() {
59604                 if (editable()) context.enter(m);
59605             });
59606         });
59607
59608         select(document)
59609             .call(keybinding);
59610
59611
59612         function update() {
59613             selection$$1.selectAll('button.add-button')
59614                 .property('disabled', !editable());
59615         }
59616     };
59617 }
59618
59619 function uiRestore(context) {
59620
59621     return function(selection) {
59622         if (!context.history().lock() || !context.history().restorableChanges())
59623             return;
59624
59625         var modalSelection = uiModal(selection, true);
59626
59627         modalSelection.select('.modal')
59628             .attr('class', 'modal fillL col6');
59629
59630         var introModal = modalSelection.select('.content');
59631
59632         introModal
59633             .attr('class','cf');
59634
59635         introModal
59636             .append('div')
59637             .attr('class', 'modal-section')
59638             .append('h3')
59639             .text(t('restore.heading'));
59640
59641         introModal
59642             .append('div')
59643             .attr('class','modal-section')
59644             .append('p')
59645             .text(t('restore.description'));
59646
59647         var buttonWrap = introModal
59648             .append('div')
59649             .attr('class', 'modal-actions cf');
59650
59651         var restore = buttonWrap
59652             .append('button')
59653             .attr('class', 'restore col6')
59654             .text(t('restore.restore'))
59655             .on('click', function() {
59656                 context.history().restore();
59657                 modalSelection.remove();
59658             });
59659
59660         buttonWrap
59661             .append('button')
59662             .attr('class', 'reset col6')
59663             .text(t('restore.reset'))
59664             .on('click', function() {
59665                 context.history().clearSaved();
59666                 modalSelection.remove();
59667             });
59668
59669         restore.node().focus();
59670     };
59671 }
59672
59673 function uiSave(context) {
59674     var history = context.history(),
59675         key = uiCmd('⌘S');
59676
59677
59678     function saving() {
59679         return context.mode().id === 'save';
59680     }
59681
59682
59683     function save() {
59684         event.preventDefault();
59685         if (!context.inIntro() && !saving() && history.hasChanges()) {
59686             context.enter(modeSave$$1(context));
59687         }
59688     }
59689
59690
59691     function getBackground(numChanges) {
59692         var step;
59693         if (numChanges === 0) {
59694             return null;
59695         } else if (numChanges <= 50) {
59696             step = numChanges / 50;
59697             return rgb$1('#fff', '#ff8')(step);  // white -> yellow
59698         } else {
59699             step = Math.min((numChanges - 50) / 50, 1.0);
59700             return rgb$1('#ff8', '#f88')(step);  // yellow -> red
59701         }
59702     }
59703
59704
59705     return function(selection$$1) {
59706         var numChanges = 0;
59707
59708         function updateCount() {
59709             var _ = history.difference().summary().length;
59710             if (_ === numChanges) return;
59711             numChanges = _;
59712
59713             tooltipBehavior
59714                 .title(uiTooltipHtml(
59715                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
59716                 );
59717
59718             var background = getBackground(numChanges);
59719
59720             button
59721                 .classed('disabled', numChanges === 0)
59722                 .classed('has-count', numChanges > 0)
59723                 .style('background', background);
59724
59725             button.select('span.count')
59726                 .text(numChanges)
59727                 .style('background', background)
59728                 .style('border-color', background);
59729         }
59730
59731
59732         var tooltipBehavior = tooltip()
59733             .placement('bottom')
59734             .html(true)
59735             .title(uiTooltipHtml(t('save.no_changes'), key));
59736
59737         var button = selection$$1
59738             .append('button')
59739             .attr('class', 'save col12 disabled')
59740             .attr('tabindex', -1)
59741             .on('click', save)
59742             .call(tooltipBehavior);
59743
59744         button
59745             .call(svgIcon('#icon-save', 'pre-text'))
59746             .append('span')
59747             .attr('class', 'label')
59748             .text(t('save.title'));
59749
59750         button
59751             .append('span')
59752             .attr('class', 'count')
59753             .text('0');
59754
59755         updateCount();
59756
59757
59758         var keybinding = d3keybinding('save')
59759             .on(key, save, true);
59760
59761         select(document)
59762             .call(keybinding);
59763
59764         context.history()
59765             .on('change.save', updateCount);
59766
59767         context
59768             .on('enter.save', function() {
59769                 button.property('disabled', saving());
59770                 if (saving()) button.call(tooltipBehavior.hide);
59771             });
59772     };
59773 }
59774
59775 function uiScale(context) {
59776     var projection = context.projection,
59777         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
59778         maxLength = 180,
59779         tickHeight = 8;
59780
59781
59782     function scaleDefs(loc1, loc2) {
59783         var lat = (loc2[1] + loc1[1]) / 2,
59784             conversion = (isImperial ? 3.28084 : 1),
59785             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
59786             scale = { dist: 0, px: 0, text: '' },
59787             buckets, i, val, dLon;
59788
59789         if (isImperial) {
59790             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
59791         } else {
59792             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
59793         }
59794
59795         // determine a user-friendly endpoint for the scale
59796         for (i = 0; i < buckets.length; i++) {
59797             val = buckets[i];
59798             if (dist >= val) {
59799                 scale.dist = Math.floor(dist / val) * val;
59800                 break;
59801             } else {
59802                 scale.dist = +dist.toFixed(2);
59803             }
59804         }
59805
59806         dLon = geoMetersToLon(scale.dist / conversion, lat);
59807         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
59808
59809         if (isImperial) {
59810             if (scale.dist >= 5280) {
59811                 scale.dist /= 5280;
59812                 scale.text = String(scale.dist) + ' mi';
59813             } else {
59814                 scale.text = String(scale.dist) + ' ft';
59815             }
59816         } else {
59817             if (scale.dist >= 1000) {
59818                 scale.dist /= 1000;
59819                 scale.text = String(scale.dist) + ' km';
59820             } else {
59821                 scale.text = String(scale.dist) + ' m';
59822             }
59823         }
59824
59825         return scale;
59826     }
59827
59828
59829     function update(selection) {
59830         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
59831         var dims = context.map().dimensions(),
59832             loc1 = projection.invert([0, dims[1]]),
59833             loc2 = projection.invert([maxLength, dims[1]]),
59834             scale = scaleDefs(loc1, loc2);
59835
59836         selection.select('#scalepath')
59837             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
59838
59839         selection.select('#scaletext')
59840             .attr('x', scale.px + 8)
59841             .attr('y', tickHeight)
59842             .text(scale.text);
59843     }
59844
59845
59846     return function(selection) {
59847         function switchUnits() {
59848             isImperial = !isImperial;
59849             selection.call(update);
59850         }
59851
59852         var g = selection.append('svg')
59853             .attr('id', 'scale')
59854             .on('click', switchUnits)
59855             .append('g')
59856             .attr('transform', 'translate(10,11)');
59857
59858         g.append('path').attr('id', 'scalepath');
59859         g.append('text').attr('id', 'scaletext');
59860
59861         selection.call(update);
59862
59863         context.map().on('move.scale', function() {
59864             update(selection);
59865         });
59866     };
59867 }
59868
59869 var pair_1 = pair;
59870 function search(x, dims, r) {
59871   if (!dims) dims = 'NSEW';
59872   if (typeof x !== 'string') return { val: null, regex: r };
59873   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
59874   var m = r.exec(x);
59875   if (!m) return { val: null, regex: r };
59876   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
59877   else return {
59878     val: (((m[1]) ? parseFloat(m[1]) : 0) +
59879           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
59880           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
59881           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
59882     regex: r,
59883     raw: m[0],
59884     dim: m[4]
59885   };
59886 }
59887
59888 function pair(x, dims) {
59889   x = x.trim();
59890   var one = search(x, dims);
59891   if (one.val === null) return null;
59892   var two = search(x, dims, one.regex);
59893   if (two.val === null) return null;
59894   // null if one/two are not contiguous.
59895   if (one.raw + two.raw !== x) return null;
59896   if (one.dim) {
59897     return swapdim(one.val, two.val, one.dim);
59898   } else {
59899     return [one.val, two.val];
59900   }
59901 }
59902
59903 function swapdim(a, b, dim) {
59904   if (dim === 'N' || dim === 'S') return [a, b];
59905   if (dim === 'W' || dim === 'E') return [b, a];
59906 }
59907
59908 function uiFeatureList(context) {
59909     var geocodeResults;
59910
59911
59912     function featureList(selection$$1) {
59913         var header = selection$$1.append('div')
59914             .attr('class', 'header fillL cf');
59915
59916         header.append('h3')
59917             .text(t('inspector.feature_list'));
59918
59919         var searchWrap = selection$$1.append('div')
59920             .attr('class', 'search-header');
59921
59922         var search = searchWrap.append('input')
59923             .attr('placeholder', t('inspector.search'))
59924             .attr('type', 'search')
59925             .on('keypress', keypress)
59926             .on('input', inputevent);
59927
59928         searchWrap
59929             .call(svgIcon('#icon-search', 'pre-text'));
59930
59931         var listWrap = selection$$1.append('div')
59932             .attr('class', 'inspector-body');
59933
59934         var list = listWrap.append('div')
59935             .attr('class', 'feature-list cf');
59936
59937         context
59938             .on('exit.feature-list', clearSearch);
59939         context.map()
59940             .on('drawn.feature-list', mapDrawn);
59941
59942
59943         function keypress() {
59944             var q = search.property('value'),
59945                 items = list.selectAll('.feature-list-item');
59946             if (event.keyCode === 13 && q.length && items.size()) {
59947                 click(items.datum());
59948             }
59949         }
59950
59951
59952         function inputevent() {
59953             geocodeResults = undefined;
59954             drawList();
59955         }
59956
59957
59958         function clearSearch() {
59959             search.property('value', '');
59960             drawList();
59961         }
59962
59963
59964         function mapDrawn(e) {
59965             if (e.full) {
59966                 drawList();
59967             }
59968         }
59969
59970
59971         function features() {
59972             var entities = {},
59973                 result = [],
59974                 graph = context.graph(),
59975                 q = search.property('value').toLowerCase();
59976
59977             if (!q) return result;
59978
59979             var idMatch = q.match(/^([nwr])([0-9]+)$/);
59980
59981             if (idMatch) {
59982                 result.push({
59983                     id: idMatch[0],
59984                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
59985                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
59986                     name: idMatch[2]
59987                 });
59988             }
59989
59990             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
59991
59992             if (locationMatch) {
59993                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
59994                 result.push({
59995                     id: -1,
59996                     geometry: 'point',
59997                     type: t('inspector.location'),
59998                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
59999                     location: loc
60000                 });
60001             }
60002
60003             function addEntity(entity) {
60004                 if (entity.id in entities || result.length > 200)
60005                     return;
60006
60007                 entities[entity.id] = true;
60008
60009                 var name = utilDisplayName(entity) || '';
60010                 if (name.toLowerCase().indexOf(q) >= 0) {
60011                     var matched = context.presets().match(entity, graph),
60012                         type = (matched && matched.name()) || utilDisplayType(entity.id);
60013                     result.push({
60014                         id: entity.id,
60015                         entity: entity,
60016                         geometry: context.geometry(entity.id),
60017                         type: type,
60018                         name: name
60019                     });
60020                 }
60021
60022                 graph.parentRelations(entity).forEach(function(parent) {
60023                     addEntity(parent);
60024                 });
60025             }
60026
60027             var visible = context.surface().selectAll('.point, .line, .area').nodes();
60028             for (var i = 0; i < visible.length && result.length <= 200; i++) {
60029                 addEntity(visible[i].__data__);
60030             }
60031
60032             (geocodeResults || []).forEach(function(d) {
60033                 // https://github.com/openstreetmap/iD/issues/1890
60034                 if (d.osm_type && d.osm_id) {
60035                     result.push({
60036                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
60037                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
60038                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
60039                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
60040                         name: d.display_name,
60041                         extent: new geoExtent$$1(
60042                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
60043                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
60044                     });
60045                 }
60046             });
60047
60048             return result;
60049         }
60050
60051
60052         function drawList() {
60053             var value = search.property('value'),
60054                 results = features();
60055
60056             list.classed('filtered', value.length);
60057
60058             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
60059
60060             var resultsIndicator = list.selectAll('.no-results-item')
60061                 .data([0])
60062                 .enter().append('button')
60063                 .property('disabled', true)
60064                 .attr('class', 'no-results-item')
60065                 .call(svgIcon('#icon-alert', 'pre-text'));
60066
60067             resultsIndicator.append('span')
60068                 .attr('class', 'entity-name');
60069
60070             list.selectAll('.no-results-item .entity-name')
60071                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
60072
60073             list.selectAll('.geocode-item')
60074                 .data([0])
60075                 .enter().append('button')
60076                 .attr('class', 'geocode-item')
60077                 .on('click', geocoderSearch)
60078                 .append('div')
60079                 .attr('class', 'label')
60080                 .append('span')
60081                 .attr('class', 'entity-name')
60082                 .text(t('geocoder.search'));
60083
60084             list.selectAll('.no-results-item')
60085                 .style('display', (value.length && !results.length) ? 'block' : 'none');
60086
60087             list.selectAll('.geocode-item')
60088                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
60089
60090             list.selectAll('.feature-list-item')
60091                 .data([-1])
60092                 .remove();
60093
60094             var items = list.selectAll('.feature-list-item')
60095                 .data(results, function(d) { return d.id; });
60096
60097             var enter = items.enter()
60098                 .insert('button', '.geocode-item')
60099                 .attr('class', 'feature-list-item')
60100                 .on('mouseover', mouseover)
60101                 .on('mouseout', mouseout)
60102                 .on('click', click);
60103
60104             var label = enter
60105                 .append('div')
60106                 .attr('class', 'label');
60107
60108             label.each(function(d) {
60109                 select(this)
60110                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
60111             });
60112
60113             label.append('span')
60114                 .attr('class', 'entity-type')
60115                 .text(function(d) { return d.type; });
60116
60117             label.append('span')
60118                 .attr('class', 'entity-name')
60119                 .text(function(d) { return d.name; });
60120
60121             enter.style('opacity', 0)
60122                 .transition()
60123                 .style('opacity', 1);
60124
60125             items.order();
60126
60127             items.exit()
60128                 .remove();
60129         }
60130
60131
60132         function mouseover(d) {
60133             if (d.id === -1) return;
60134
60135             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
60136                 .classed('hover', true);
60137         }
60138
60139
60140         function mouseout() {
60141             context.surface().selectAll('.hover')
60142                 .classed('hover', false);
60143         }
60144
60145
60146         function click(d) {
60147             event.preventDefault();
60148             if (d.location) {
60149                 context.map().centerZoom([d.location[1], d.location[0]], 20);
60150             }
60151             else if (d.entity) {
60152                 if (d.entity.type === 'node') {
60153                     context.map().center(d.entity.loc);
60154                 } else if (d.entity.type === 'way') {
60155                     var center = context.projection(context.map().center()),
60156                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
60157                     context.map().center(edge.loc);
60158                 }
60159                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
60160             } else {
60161                 context.zoomToEntity(d.id);
60162             }
60163         }
60164
60165
60166         function geocoderSearch() {
60167             services.geocoder.search(search.property('value'), function (err, resp) {
60168                 geocodeResults = resp || [];
60169                 drawList();
60170             });
60171         }
60172     }
60173
60174
60175     return featureList;
60176 }
60177
60178 function uiPresetIcon() {
60179     var preset, geometry;
60180
60181
60182     function presetIcon(selection$$1) {
60183         selection$$1.each(render);
60184     }
60185
60186
60187     function render() {
60188         var selection$$1 = select(this),
60189             p = preset.apply(this, arguments),
60190             geom = geometry.apply(this, arguments),
60191             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
60192             isMaki = dataFeatureIcons.indexOf(picon) !== -1;
60193
60194         function tag_classes(p) {
60195             var s = '';
60196             for (var i in p.tags) {
60197                 s += ' tag-' + i;
60198                 if (p.tags[i] !== '*') {
60199                     s += ' tag-' + i + '-' + p.tags[i];
60200                 }
60201             }
60202             return s;
60203         }
60204
60205         var fill = selection$$1.selectAll('.preset-icon-fill')
60206             .data([0]);
60207
60208         fill = fill.enter()
60209             .append('div')
60210             .merge(fill);
60211
60212         fill
60213             .attr('class', function() {
60214                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
60215             });
60216
60217         var frame = selection$$1.selectAll('.preset-icon-frame')
60218             .data([0]);
60219
60220         frame = frame.enter()
60221             .append('div')
60222             .call(svgIcon('#preset-icon-frame'))
60223             .merge(frame);
60224
60225         frame
60226             .attr('class', function() {
60227                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
60228             });
60229
60230
60231         var icon = selection$$1.selectAll('.preset-icon')
60232             .data([0]);
60233
60234         icon = icon.enter()
60235             .append('div')
60236             .attr('class', 'preset-icon')
60237             .call(svgIcon(''))
60238             .merge(icon);
60239
60240         icon
60241             .attr('class', 'preset-icon preset-icon-' +
60242                 (isMaki ? (geom === 'area' ? '24' : '28') : (geom === 'area' ? '44' : '60'))
60243             );
60244
60245         icon.selectAll('svg')
60246             .attr('class', function() {
60247                 return 'icon ' + picon + (isMaki ? '' : tag_classes(p));
60248             });
60249
60250         icon.selectAll('use')
60251             .attr('href', '#' + picon + (isMaki ? '-15' : ''));
60252     }
60253
60254
60255     presetIcon.preset = function(_) {
60256         if (!arguments.length) return preset;
60257         preset = utilFunctor(_);
60258         return presetIcon;
60259     };
60260
60261
60262     presetIcon.geometry = function(_) {
60263         if (!arguments.length) return geometry;
60264         geometry = utilFunctor(_);
60265         return presetIcon;
60266     };
60267
60268     return presetIcon;
60269 }
60270
60271 function d3combobox() {
60272     var event$$1 = dispatch('accept'),
60273         data = [],
60274         suggestions = [],
60275         minItems = 2,
60276         caseSensitive = false;
60277
60278     var fetcher = function(val, cb) {
60279         cb(data.filter(function(d) {
60280             return d.value
60281                 .toString()
60282                 .toLowerCase()
60283                 .indexOf(val.toLowerCase()) !== -1;
60284         }));
60285     };
60286
60287     var combobox = function(input, attachTo) {
60288         var idx = -1,
60289             container = select(document.body)
60290                 .selectAll('div.combobox')
60291                 .filter(function(d) { return d === input.node(); }),
60292             shown = !container.empty();
60293
60294         input
60295             .classed('combobox-input', true)
60296             .on('focus.typeahead', focus)
60297             .on('blur.typeahead', blur)
60298             .on('keydown.typeahead', keydown)
60299             .on('keyup.typeahead', keyup)
60300             .on('input.typeahead', change)
60301             .each(function() {
60302                 var parent = this.parentNode,
60303                     sibling = this.nextSibling;
60304
60305                 var caret = select(parent).selectAll('.combobox-caret')
60306                     .filter(function(d) { return d === input.node(); })
60307                     .data([input.node()]);
60308
60309                 caret = caret.enter()
60310                   .insert('div', function() { return sibling; })
60311                     .attr('class', 'combobox-caret')
60312                   .merge(caret);
60313
60314                 caret
60315                     .on('mousedown', function () {
60316                         // prevent the form element from blurring. it blurs
60317                         // on mousedown
60318                         event.stopPropagation();
60319                         event.preventDefault();
60320                         if (!shown) {
60321                             input.node().focus();
60322                             fetch('', render);
60323                         } else {
60324                             hide();
60325                         }
60326                     });
60327             });
60328
60329         function focus() {
60330             fetch(value(), render);
60331         }
60332
60333         function blur() {
60334             window.setTimeout(hide, 150);
60335         }
60336
60337         function show() {
60338             if (!shown) {
60339                 container = select(document.body)
60340                     .insert('div', ':first-child')
60341                     .datum(input.node())
60342                     .attr('class', 'combobox')
60343                     .style('position', 'absolute')
60344                     .style('display', 'block')
60345                     .style('left', '0px')
60346                     .on('mousedown', function () {
60347                         // prevent moving focus out of the text field
60348                         event.preventDefault();
60349                     });
60350
60351                 select(document.body)
60352                     .on('scroll.combobox', render, true);
60353
60354                 shown = true;
60355             }
60356         }
60357
60358         function hide() {
60359             if (shown) {
60360                 idx = -1;
60361                 container.remove();
60362
60363                 select(document.body)
60364                     .on('scroll.combobox', null);
60365
60366                 shown = false;
60367             }
60368         }
60369
60370         function keydown() {
60371            switch (event.keyCode) {
60372                // backspace, delete
60373                case 8:
60374                case 46:
60375                    input.on('input.typeahead', function() {
60376                        idx = -1;
60377                        render();
60378                        var start = input.property('selectionStart');
60379                        input.node().setSelectionRange(start, start);
60380                        input.on('input.typeahead', change);
60381                    });
60382                    break;
60383                // tab
60384                case 9:
60385                    container.selectAll('a.selected').each(function (d) {
60386                        event$$1.call('accept', this, d);
60387                    });
60388                    hide();
60389                    break;
60390                // return
60391                case 13:
60392                    event.preventDefault();
60393                    break;
60394                // up arrow
60395                case 38:
60396                    nav(-1);
60397                    event.preventDefault();
60398                    break;
60399                // down arrow
60400                case 40:
60401                    nav(+1);
60402                    event.preventDefault();
60403                    break;
60404            }
60405            event.stopPropagation();
60406         }
60407
60408         function keyup() {
60409             switch (event.keyCode) {
60410                 // escape
60411                 case 27:
60412                     hide();
60413                     break;
60414                 // return
60415                 case 13:
60416                     container.selectAll('a.selected').each(function (d) {
60417                        event$$1.call('accept', this, d);
60418                     });
60419                     hide();
60420                     break;
60421             }
60422         }
60423
60424         function change() {
60425             fetch(value(), function() {
60426                 if (input.property('selectionEnd') === input.property('value').length) {
60427                     autocomplete();
60428                 }
60429                 render();
60430             });
60431         }
60432
60433         function nav(dir) {
60434             if (!suggestions.length) return;
60435             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
60436             input.property('value', suggestions[idx].value);
60437             render();
60438             ensureVisible();
60439         }
60440
60441         function value() {
60442             var value = input.property('value'),
60443                 start = input.property('selectionStart'),
60444                 end = input.property('selectionEnd');
60445
60446             if (start && end) {
60447                 value = value.substring(0, start);
60448             }
60449
60450             return value;
60451         }
60452
60453         function fetch(v, cb) {
60454             fetcher.call(input, v, function(_) {
60455                 suggestions = _;
60456                 cb();
60457             });
60458         }
60459
60460         function autocomplete() {
60461             var v = caseSensitive ? value() : value().toLowerCase();
60462             idx = -1;
60463             if (!v) return;
60464
60465             for (var i = 0; i < suggestions.length; i++) {
60466                 var suggestion = suggestions[i].value,
60467                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
60468
60469                 if (compare.indexOf(v) === 0) {
60470                     idx = i;
60471                     input.property('value', suggestion);
60472                     input.node().setSelectionRange(v.length, suggestion.length);
60473                     return;
60474                 }
60475             }
60476         }
60477
60478         function render() {
60479             if (suggestions.length >= minItems && document.activeElement === input.node()) {
60480                 show();
60481             } else {
60482                 hide();
60483                 return;
60484             }
60485
60486             var options = container
60487                 .selectAll('a.combobox-option')
60488                 .data(suggestions, function(d) { return d.value; });
60489
60490             options.exit()
60491                 .remove();
60492
60493             options.enter()
60494                 .append('a')
60495                 .attr('class', 'combobox-option')
60496                 .text(function(d) { return d.value; })
60497                 .merge(options)
60498                 .attr('title', function(d) { return d.title; })
60499                 .classed('selected', function(d, i) { return i === idx; })
60500                 .on('mouseover', select$$1)
60501                 .on('click', accept)
60502                 .order();
60503
60504
60505             var node = attachTo ? attachTo.node() : input.node(),
60506                 rect = node.getBoundingClientRect();
60507
60508             container
60509                 .style('left', rect.left + 'px')
60510                 .style('width', rect.width + 'px')
60511                 .style('top', rect.height + rect.top + 'px');
60512         }
60513
60514         function select$$1(d, i) {
60515             idx = i;
60516             render();
60517         }
60518
60519         function ensureVisible() {
60520             var node = container.selectAll('a.selected').node();
60521             if (node) node.scrollIntoView();
60522         }
60523
60524         function accept(d) {
60525             if (!shown) return;
60526             input
60527                 .property('value', d.value)
60528                 .dispatch('change');
60529             event$$1.call('accept', this, d);
60530             hide();
60531         }
60532     };
60533
60534     combobox.fetcher = function(_) {
60535         if (!arguments.length) return fetcher;
60536         fetcher = _;
60537         return combobox;
60538     };
60539
60540     combobox.data = function(_) {
60541         if (!arguments.length) return data;
60542         data = _;
60543         return combobox;
60544     };
60545
60546     combobox.minItems = function(_) {
60547         if (!arguments.length) return minItems;
60548         minItems = _;
60549         return combobox;
60550     };
60551
60552     combobox.caseSensitive = function(_) {
60553         if (!arguments.length) return caseSensitive;
60554         caseSensitive = _;
60555         return combobox;
60556     };
60557
60558     return utilRebind(combobox, event$$1, 'on');
60559 }
60560
60561
60562 d3combobox.off = function(input) {
60563     input
60564         .on('focus.typeahead', null)
60565         .on('blur.typeahead', null)
60566         .on('keydown.typeahead', null)
60567         .on('keyup.typeahead', null)
60568         .on('input.typeahead', null)
60569         .each(function() {
60570             select(this.parentNode).selectAll('.combobox-caret')
60571                 .filter(function(d) { return d === input.node(); })
60572                 .on('mousedown', null);
60573         });
60574
60575     select(document.body)
60576         .on('scroll.combobox', null);
60577 };
60578
60579 function uiDisclosure() {
60580     var dispatch$$1 = dispatch('toggled'),
60581         title,
60582         expanded = false,
60583         content = function () {};
60584
60585
60586     var disclosure = function(selection$$1) {
60587         var hideToggle = selection$$1.selectAll('.hide-toggle')
60588             .data([0]);
60589
60590         hideToggle = hideToggle.enter()
60591             .append('a')
60592             .attr('href', '#')
60593             .attr('class', 'hide-toggle')
60594             .merge(hideToggle);
60595
60596         hideToggle
60597             .text(title)
60598             .on('click', toggle)
60599             .classed('expanded', expanded);
60600
60601
60602         var wrap = selection$$1.selectAll('div')
60603             .data([0]);
60604
60605         wrap = wrap.enter()
60606             .append('div')
60607             .merge(wrap);
60608
60609         wrap
60610             .classed('hide', !expanded)
60611             .call(content);
60612
60613
60614         function toggle() {
60615             expanded = !expanded;
60616             hideToggle.classed('expanded', expanded);
60617             wrap.call(uiToggle(expanded));
60618             dispatch$$1.call('toggled', this, expanded);
60619         }
60620     };
60621
60622
60623     disclosure.title = function(_) {
60624         if (!arguments.length) return title;
60625         title = _;
60626         return disclosure;
60627     };
60628
60629
60630     disclosure.expanded = function(_) {
60631         if (!arguments.length) return expanded;
60632         expanded = _;
60633         return disclosure;
60634     };
60635
60636
60637     disclosure.content = function(_) {
60638         if (!arguments.length) return content;
60639         content = _;
60640         return disclosure;
60641     };
60642
60643
60644     return utilRebind(disclosure, dispatch$$1, 'on');
60645 }
60646
60647 function uiRawMemberEditor(context) {
60648     var id,
60649         taginfo = services.taginfo;
60650
60651
60652     function selectMember(d) {
60653         event.preventDefault();
60654         context.enter(modeSelect(context, [d.id]).suppressMenu(true));
60655     }
60656
60657
60658     function changeRole(d) {
60659         var role = select(this).property('value');
60660         var member = { id: d.id, type: d.type, role: role };
60661         context.perform(
60662             actionChangeMember(d.relation.id, member, d.index),
60663             t('operations.change_role.annotation')
60664         );
60665     }
60666
60667
60668     function deleteMember(d) {
60669         context.perform(
60670             actionDeleteMember(d.relation.id, d.index),
60671             t('operations.delete_member.annotation')
60672         );
60673
60674         if (!context.hasEntity(d.relation.id)) {
60675             context.enter(modeBrowse(context));
60676         }
60677     }
60678
60679
60680     function rawMemberEditor(selection$$1) {
60681         var entity = context.entity(id),
60682             memberships = [];
60683
60684         entity.members.forEach(function(member, index) {
60685             memberships.push({
60686                 index: index,
60687                 id: member.id,
60688                 type: member.type,
60689                 role: member.role,
60690                 relation: entity,
60691                 member: context.hasEntity(member.id)
60692             });
60693         });
60694
60695         selection$$1.call(uiDisclosure()
60696             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
60697             .expanded(true)
60698             .on('toggled', toggled)
60699             .content(content)
60700         );
60701
60702
60703         function toggled(expanded) {
60704             if (expanded) {
60705                 selection$$1.node().parentNode.scrollTop += 200;
60706             }
60707         }
60708
60709
60710         function content(wrap) {
60711             var list = wrap.selectAll('.member-list')
60712                 .data([0]);
60713
60714             list = list.enter()
60715                 .append('ul')
60716                 .attr('class', 'member-list')
60717                 .merge(list);
60718
60719
60720             var items = list.selectAll('li')
60721                 .data(memberships, function(d) {
60722                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
60723                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
60724                 });
60725
60726             items.exit()
60727                 .each(unbind)
60728                 .remove();
60729
60730             var enter = items.enter()
60731                 .append('li')
60732                 .attr('class', 'member-row form-field')
60733                 .classed('member-incomplete', function(d) { return !d.member; });
60734
60735             enter
60736                 .each(function(d) {
60737                     if (d.member) {
60738                         var label = select(this).append('label')
60739                             .attr('class', 'form-label')
60740                             .append('a')
60741                             .attr('href', '#')
60742                             .on('click', selectMember);
60743
60744                         label.append('span')
60745                             .attr('class', 'member-entity-type')
60746                             .text(function(d) {
60747                                 var matched = context.presets().match(d.member, context.graph());
60748                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
60749                             });
60750
60751                         label.append('span')
60752                             .attr('class', 'member-entity-name')
60753                             .text(function(d) { return utilDisplayName(d.member); });
60754
60755                     } else {
60756                         select(this).append('label')
60757                             .attr('class', 'form-label')
60758                             .text(t('inspector.incomplete', { id: d.id }));
60759                     }
60760                 });
60761
60762             enter
60763                 .append('input')
60764                 .attr('class', 'member-role')
60765                 .property('type', 'text')
60766                 .attr('maxlength', 255)
60767                 .attr('placeholder', t('inspector.role'))
60768                 .property('value', function(d) { return d.role; })
60769                 .on('change', changeRole);
60770
60771             enter
60772                 .append('button')
60773                 .attr('tabindex', -1)
60774                 .attr('class', 'remove button-input-action member-delete minor')
60775                 .on('click', deleteMember)
60776                 .call(svgIcon('#operation-delete'));
60777
60778             if (taginfo) {
60779                 enter.each(bindTypeahead);
60780             }
60781
60782
60783             function bindTypeahead(d) {
60784                 var row = select(this),
60785                     role = row.selectAll('input.member-role');
60786
60787                 function sort(value, data) {
60788                     var sameletter = [],
60789                         other = [];
60790                     for (var i = 0; i < data.length; i++) {
60791                         if (data[i].value.substring(0, value.length) === value) {
60792                             sameletter.push(data[i]);
60793                         } else {
60794                             other.push(data[i]);
60795                         }
60796                     }
60797                     return sameletter.concat(other);
60798                 }
60799
60800                 role.call(d3combobox()
60801                     .fetcher(function(role, callback) {
60802                         var rtype = entity.tags.type;
60803                         taginfo.roles({
60804                             debounce: true,
60805                             rtype: rtype || '',
60806                             geometry: context.geometry(d.member.id),
60807                             query: role
60808                         }, function(err, data) {
60809                             if (!err) callback(sort(role, data));
60810                         });
60811                     }));
60812             }
60813
60814
60815             function unbind() {
60816                 var row = select(this);
60817
60818                 row.selectAll('input.member-role')
60819                     .call(d3combobox.off);
60820             }
60821         }
60822     }
60823
60824
60825     rawMemberEditor.entityID = function(_) {
60826         if (!arguments.length) return id;
60827         id = _;
60828         return rawMemberEditor;
60829     };
60830
60831
60832     return rawMemberEditor;
60833 }
60834
60835 function uiRawMembershipEditor(context) {
60836     var taginfo = services.taginfo,
60837         id, showBlank;
60838
60839
60840     function selectRelation(d) {
60841         event.preventDefault();
60842         context.enter(modeSelect(context, [d.relation.id]).suppressMenu(true));
60843     }
60844
60845
60846     function changeRole(d) {
60847         var role = select(this).property('value');
60848         context.perform(
60849             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
60850             t('operations.change_role.annotation')
60851         );
60852     }
60853
60854
60855     function addMembership(d, role) {
60856         showBlank = false;
60857
60858         if (d.relation) {
60859             context.perform(
60860                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
60861                 t('operations.add_member.annotation')
60862             );
60863
60864         } else {
60865             var relation = osmRelation();
60866             context.perform(
60867                 actionAddEntity(relation),
60868                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
60869                 t('operations.add.annotation.relation')
60870             );
60871
60872             context.enter(modeSelect(context, [relation.id]).suppressMenu(true));
60873         }
60874     }
60875
60876
60877     function deleteMembership(d) {
60878         context.perform(
60879             actionDeleteMember(d.relation.id, d.index),
60880             t('operations.delete_member.annotation')
60881         );
60882     }
60883
60884
60885     function relations(q) {
60886         var newRelation = {
60887                 relation: null,
60888                 value: t('inspector.new_relation')
60889             },
60890             result = [],
60891             graph = context.graph();
60892
60893         context.intersects(context.extent()).forEach(function(entity) {
60894             if (entity.type !== 'relation' || entity.id === id)
60895                 return;
60896
60897             var matched = context.presets().match(entity, graph),
60898                 presetName = (matched && matched.name()) || t('inspector.relation'),
60899                 entityName = utilDisplayName(entity) || '';
60900
60901             var value = presetName + ' ' + entityName;
60902             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
60903                 return;
60904
60905             result.push({
60906                 relation: entity,
60907                 value: value
60908             });
60909         });
60910
60911         result.sort(function(a, b) {
60912             return osmRelation.creationOrder(a.relation, b.relation);
60913         });
60914
60915         // Dedupe identical names by appending relation id - see #2891
60916         var dupeGroups = lodash(result)
60917             .groupBy('value')
60918             .filter(function(v) { return v.length > 1; })
60919             .value();
60920
60921         dupeGroups.forEach(function(group) {
60922             group.forEach(function(obj) {
60923                 obj.value += ' ' + obj.relation.id;
60924             });
60925         });
60926
60927         result.unshift(newRelation);
60928         return result;
60929     }
60930
60931
60932     function rawMembershipEditor(selection$$1) {
60933         var entity = context.entity(id),
60934             memberships = [];
60935
60936         context.graph().parentRelations(entity).forEach(function(relation) {
60937             relation.members.forEach(function(member, index) {
60938                 if (member.id === entity.id) {
60939                     memberships.push({ relation: relation, member: member, index: index });
60940                 }
60941             });
60942         });
60943
60944         selection$$1.call(uiDisclosure()
60945             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
60946             .expanded(true)
60947             .on('toggled', toggled)
60948             .content(content)
60949         );
60950
60951
60952         function toggled(expanded) {
60953             if (expanded) {
60954                 selection$$1.node().parentNode.scrollTop += 200;
60955             }
60956         }
60957
60958
60959         function content(wrap) {
60960             var list = wrap.selectAll('.member-list')
60961                 .data([0]);
60962
60963             list = list.enter()
60964                 .append('ul')
60965                 .attr('class', 'member-list')
60966                 .merge(list);
60967
60968
60969             var items = list.selectAll('li.member-row-normal')
60970                 .data(memberships, function(d) {
60971                     return osmEntity$$1.key(d.relation) + ',' + d.index;
60972                 });
60973
60974             items.exit()
60975                 .each(unbind)
60976                 .remove();
60977
60978             var enter = items.enter()
60979                 .append('li')
60980                 .attr('class', 'member-row member-row-normal form-field');
60981
60982             var label = enter
60983                 .append('label')
60984                 .attr('class', 'form-label')
60985                 .append('a')
60986                 .attr('href', '#')
60987                 .on('click', selectRelation);
60988
60989             label
60990                 .append('span')
60991                 .attr('class', 'member-entity-type')
60992                 .text(function(d) {
60993                     var matched = context.presets().match(d.relation, context.graph());
60994                     return (matched && matched.name()) || t('inspector.relation');
60995                 });
60996
60997             label
60998                 .append('span')
60999                 .attr('class', 'member-entity-name')
61000                 .text(function(d) { return utilDisplayName(d.relation); });
61001
61002             enter
61003                 .append('input')
61004                 .attr('class', 'member-role')
61005                 .property('type', 'text')
61006                 .attr('maxlength', 255)
61007                 .attr('placeholder', t('inspector.role'))
61008                 .property('value', function(d) { return d.member.role; })
61009                 .on('change', changeRole);
61010
61011             enter
61012                 .append('button')
61013                 .attr('tabindex', -1)
61014                 .attr('class', 'remove button-input-action member-delete minor')
61015                 .on('click', deleteMembership)
61016                 .call(svgIcon('#operation-delete'));
61017
61018             if (taginfo) {
61019                 enter.each(bindTypeahead);
61020             }
61021
61022
61023             var newrow = list.selectAll('.member-row-new')
61024                 .data(showBlank ? [0] : []);
61025
61026             newrow.exit()
61027                 .remove();
61028
61029             enter = newrow.enter()
61030                 .append('li')
61031                 .attr('class', 'member-row member-row-new form-field');
61032
61033             enter
61034                 .append('input')
61035                 .attr('type', 'text')
61036                 .attr('class', 'member-entity-input');
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                 .on('change', changeRole);
61045
61046             enter
61047                 .append('button')
61048                 .attr('tabindex', -1)
61049                 .attr('class', 'remove button-input-action member-delete minor')
61050                 .on('click', deleteMembership)
61051                 .call(svgIcon('#operation-delete'));
61052
61053             newrow = newrow
61054                 .merge(enter);
61055
61056             newrow.selectAll('.member-entity-input')
61057                 .call(d3combobox()
61058                     .minItems(1)
61059                     .fetcher(function(value, callback) { callback(relations(value)); })
61060                     .on('accept', onAccept)
61061                 );
61062
61063
61064             var addrel = wrap.selectAll('.add-relation')
61065                 .data([0]);
61066
61067             addrel = addrel.enter()
61068                 .append('button')
61069                 .attr('class', 'add-relation')
61070                 .merge(addrel);
61071
61072             addrel
61073                 .call(svgIcon('#icon-plus', 'light'))
61074                 .on('click', function() {
61075                     showBlank = true;
61076                     content(wrap);
61077                     list.selectAll('.member-entity-input').node().focus();
61078                 });
61079
61080
61081             function onAccept(d) {
61082                 var role = list.selectAll('.member-row-new .member-role').property('value');
61083                 addMembership(d, role);
61084             }
61085
61086
61087             function bindTypeahead(d) {
61088                 var row = select(this),
61089                     role = row.selectAll('input.member-role');
61090
61091                 function sort(value, data) {
61092                     var sameletter = [],
61093                         other = [];
61094                     for (var i = 0; i < data.length; i++) {
61095                         if (data[i].value.substring(0, value.length) === value) {
61096                             sameletter.push(data[i]);
61097                         } else {
61098                             other.push(data[i]);
61099                         }
61100                     }
61101                     return sameletter.concat(other);
61102                 }
61103
61104                 role.call(d3combobox()
61105                     .fetcher(function(role, callback) {
61106                         var rtype = d.relation.tags.type;
61107                         taginfo.roles({
61108                             debounce: true,
61109                             rtype: rtype || '',
61110                             geometry: context.geometry(id),
61111                             query: role
61112                         }, function(err, data) {
61113                             if (!err) callback(sort(role, data));
61114                         });
61115                     }));
61116             }
61117
61118
61119             function unbind() {
61120                 var row = select(this);
61121
61122                 row.selectAll('input.member-role')
61123                     .call(d3combobox.off);
61124             }
61125         }
61126     }
61127
61128
61129     rawMembershipEditor.entityID = function(_) {
61130         if (!arguments.length) return id;
61131         id = _;
61132         return rawMembershipEditor;
61133     };
61134
61135
61136     return rawMembershipEditor;
61137 }
61138
61139 function uiTagReference(tag) {
61140     var taginfo = services.taginfo,
61141         tagReference = {},
61142         button,
61143         body,
61144         loaded,
61145         showing;
61146
61147
61148     function findLocal(data) {
61149         var locale = utilDetect().locale.toLowerCase(),
61150             localized;
61151
61152         if (locale !== 'pt-br') {  // see #3776, prefer 'pt' over 'pt-br'
61153             localized = lodash.find(data, function(d) {
61154                 return d.lang.toLowerCase() === locale;
61155             });
61156             if (localized) return localized;
61157         }
61158
61159         // try the non-regional version of a language, like
61160         // 'en' if the language is 'en-US'
61161         if (locale.indexOf('-') !== -1) {
61162             var first = locale.split('-')[0];
61163             localized = lodash.find(data, function(d) {
61164                 return d.lang.toLowerCase() === first;
61165             });
61166             if (localized) return localized;
61167         }
61168
61169         // finally fall back to english
61170         return lodash.find(data, function(d) {
61171             return d.lang.toLowerCase() === 'en';
61172         });
61173     }
61174
61175
61176     function load(param) {
61177         if (!taginfo) return;
61178
61179         button.classed('tag-reference-loading', true);
61180
61181         taginfo.docs(param, function show(err, data) {
61182             var docs;
61183             if (!err && data) {
61184                 docs = findLocal(data);
61185             }
61186
61187             body.html('');
61188
61189
61190             if (!docs || !docs.title) {
61191                 if (param.hasOwnProperty('value')) {
61192                     load(lodash.omit(param, 'value'));   // retry with key only
61193                 } else {
61194                     body.append('p').text(t('inspector.no_documentation_key'));
61195                     done();
61196                 }
61197                 return;
61198             }
61199
61200
61201             if (docs.image && docs.image.thumb_url_prefix) {
61202                 body
61203                     .append('img')
61204                     .attr('class', 'wiki-image')
61205                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
61206                     .on('load', function() { done(); })
61207                     .on('error', function() { select(this).remove(); done(); });
61208             } else {
61209                 done();
61210             }
61211
61212             body
61213                 .append('p')
61214                 .text(docs.description || t('inspector.documentation_redirect'));
61215
61216             body
61217                 .append('a')
61218                 .attr('target', '_blank')
61219                 .attr('tabindex', -1)
61220                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
61221                 .call(svgIcon('#icon-out-link', 'inline'))
61222                 .append('span')
61223                 .text(t('inspector.reference'));
61224         });
61225     }
61226
61227
61228     function done() {
61229         loaded = true;
61230
61231         button.classed('tag-reference-loading', false);
61232
61233         body.transition()
61234             .duration(200)
61235             .style('max-height', '200px')
61236             .style('opacity', '1');
61237
61238         showing = true;
61239     }
61240
61241
61242     function hide(selection$$1) {
61243         selection$$1 = selection$$1 || body.transition().duration(200);
61244
61245         selection$$1
61246             .style('max-height', '0px')
61247             .style('opacity', '0');
61248
61249         showing = false;
61250     }
61251
61252
61253     tagReference.button = function(selection$$1) {
61254         button = selection$$1.selectAll('.tag-reference-button')
61255             .data([0]);
61256
61257         button = button.enter()
61258             .append('button')
61259             .attr('class', 'tag-reference-button')
61260             .attr('tabindex', -1)
61261             .call(svgIcon('#icon-inspect'))
61262             .merge(button);
61263
61264         button
61265             .on('click', function () {
61266                 event.stopPropagation();
61267                 event.preventDefault();
61268                 if (showing) {
61269                     hide();
61270                 } else if (loaded) {
61271                     done();
61272                 } else {
61273                     load(tag);
61274                 }
61275             });
61276     };
61277
61278
61279     tagReference.body = function(selection$$1) {
61280         body = selection$$1.selectAll('.tag-reference-body')
61281             .data([0]);
61282
61283         body = body.enter()
61284             .append('div')
61285             .attr('class', 'tag-reference-body cf')
61286             .style('max-height', '0')
61287             .style('opacity', '0')
61288             .merge(body);
61289
61290         if (showing === false) {
61291             hide(body);
61292         }
61293     };
61294
61295
61296     tagReference.showing = function(_) {
61297         if (!arguments.length) return showing;
61298         showing = _;
61299         return tagReference;
61300     };
61301
61302
61303     return tagReference;
61304 }
61305
61306 function uiRawTagEditor(context) {
61307     var taginfo = services.taginfo,
61308         dispatch$$1 = dispatch('change'),
61309         showBlank = false,
61310         state,
61311         preset,
61312         tags,
61313         id;
61314
61315
61316     function rawTagEditor(selection$$1) {
61317         var count = Object.keys(tags).filter(function(d) { return d; }).length;
61318
61319         selection$$1.call(uiDisclosure()
61320             .title(t('inspector.all_tags') + ' (' + count + ')')
61321             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
61322             .on('toggled', toggled)
61323             .content(content));
61324
61325         function toggled(expanded) {
61326             context.storage('raw_tag_editor.expanded', expanded);
61327             if (expanded) {
61328                 selection$$1.node().parentNode.scrollTop += 200;
61329             }
61330         }
61331     }
61332
61333
61334     function content(wrap) {
61335         var entries$$1 = entries(tags);
61336
61337         if (!entries$$1.length || showBlank) {
61338             showBlank = false;
61339             entries$$1.push({key: '', value: ''});
61340         }
61341
61342         var list = wrap.selectAll('.tag-list')
61343             .data([0]);
61344
61345         list = list.enter()
61346             .append('ul')
61347             .attr('class', 'tag-list')
61348             .merge(list);
61349
61350         var newTag = wrap.selectAll('.add-tag')
61351             .data([0]);
61352
61353         newTag.enter()
61354             .append('button')
61355             .attr('class', 'add-tag')
61356             .on('click', addTag)
61357             .call(svgIcon('#icon-plus', 'light'));
61358
61359
61360         var items = list.selectAll('.tag-row')
61361             .data(entries$$1, function(d) { return d.key; });
61362
61363         items.exit()
61364             .each(unbind)
61365             .remove();
61366
61367         // Enter
61368
61369         var enter = items.enter()
61370             .append('li')
61371             .attr('class', 'tag-row cf');
61372
61373         enter
61374             .append('div')
61375             .attr('class', 'key-wrap')
61376             .append('input')
61377             .property('type', 'text')
61378             .attr('class', 'key')
61379             .attr('maxlength', 255)
61380             .on('blur', keyChange)
61381             .on('change', keyChange);
61382
61383         enter
61384             .append('div')
61385             .attr('class', 'input-wrap-position')
61386             .append('input')
61387             .property('type', 'text')
61388             .attr('class', 'value')
61389             .attr('maxlength', 255)
61390             .on('blur', valueChange)
61391             .on('change', valueChange)
61392             .on('keydown.push-more', pushMore);
61393
61394         enter
61395             .append('button')
61396             .attr('tabindex', -1)
61397             .attr('class', 'remove minor')
61398             .call(svgIcon('#operation-delete'));
61399
61400
61401         // Update
61402
61403         items = items
61404             .merge(enter)
61405             .sort(function(a, b) {
61406                 return (a.key === '') ? 1
61407                     : (b.key === '') ? -1
61408                     : ascending(a.key, b.key);
61409             });
61410
61411         items
61412             .each(function(tag) {
61413                 var row = select(this),
61414                     key = row.select('input.key'),      // propagate bound data to child
61415                     value = row.select('input.value');  // propagate bound data to child
61416
61417                 if (taginfo) {
61418                     bindTypeahead(key, value);
61419                 }
61420
61421                 var isRelation = (context.entity(id).type === 'relation'),
61422                     reference;
61423
61424                 if (isRelation && tag.key === 'type') {
61425                     reference = uiTagReference({ rtype: tag.value }, context);
61426                 } else {
61427                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
61428                 }
61429
61430                 if (state === 'hover') {
61431                     reference.showing(false);
61432                 }
61433
61434                 row
61435                     .call(reference.button)
61436                     .call(reference.body);
61437             });
61438
61439         items.selectAll('input.key')
61440             .attr('title', function(d) { return d.key; })
61441             .call(utilGetSetValue, function(d) { return d.key; });
61442
61443         items.selectAll('input.value')
61444             .attr('title', function(d) { return d.value; })
61445             .call(utilGetSetValue, function(d) { return d.value; });
61446
61447         items.selectAll('button.remove')
61448             .on('click', removeTag);
61449
61450
61451         function pushMore() {
61452             if (event.keyCode === 9 && !event.shiftKey &&
61453                 list.selectAll('li:last-child input.value').node() === this) {
61454                 addTag();
61455             }
61456         }
61457
61458
61459         function bindTypeahead(key, value) {
61460
61461             function sort(value, data) {
61462                 var sameletter = [],
61463                     other = [];
61464                 for (var i = 0; i < data.length; i++) {
61465                     if (data[i].value.substring(0, value.length) === value) {
61466                         sameletter.push(data[i]);
61467                     } else {
61468                         other.push(data[i]);
61469                     }
61470                 }
61471                 return sameletter.concat(other);
61472             }
61473
61474             key.call(d3combobox()
61475                 .fetcher(function(value, callback) {
61476                     taginfo.keys({
61477                         debounce: true,
61478                         geometry: context.geometry(id),
61479                         query: value
61480                     }, function(err, data) {
61481                         if (!err) callback(sort(value, data));
61482                     });
61483                 }));
61484
61485             value.call(d3combobox()
61486                 .fetcher(function(value, callback) {
61487                     taginfo.values({
61488                         debounce: true,
61489                         key: utilGetSetValue(key),
61490                         geometry: context.geometry(id),
61491                         query: value
61492                     }, function(err, data) {
61493                         if (!err) callback(sort(value, data));
61494                     });
61495                 }));
61496         }
61497
61498
61499         function unbind() {
61500             var row = select(this);
61501
61502             row.selectAll('input.key')
61503                 .call(d3combobox.off);
61504
61505             row.selectAll('input.value')
61506                 .call(d3combobox.off);
61507         }
61508
61509
61510         function keyChange(d) {
61511             var kOld = d.key,
61512                 kNew = this.value.trim(),
61513                 tag = {};
61514
61515             if (kNew && kNew !== kOld) {
61516                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
61517                     base = match[1],
61518                     suffix = +(match[2] || 1);
61519                 while (tags[kNew]) {  // rename key if already in use
61520                     kNew = base + '_' + suffix++;
61521                 }
61522             }
61523             tag[kOld] = undefined;
61524             tag[kNew] = d.value;
61525             d.key = kNew; // Maintain DOM identity through the subsequent update.
61526             this.value = kNew;
61527             dispatch$$1.call('change', this, tag);
61528         }
61529
61530
61531         function valueChange(d) {
61532             var tag = {};
61533             tag[d.key] = this.value;
61534             dispatch$$1.call('change', this, tag);
61535         }
61536
61537
61538         function removeTag(d) {
61539             var tag = {};
61540             tag[d.key] = undefined;
61541             dispatch$$1.call('change', this, tag);
61542             select(this.parentNode).remove();
61543         }
61544
61545
61546         function addTag() {
61547             // Wrapped in a setTimeout in case it's being called from a blur
61548             // handler. Without the setTimeout, the call to `content` would
61549             // wipe out the pending value change.
61550             setTimeout(function() {
61551                 showBlank = true;
61552                 content(wrap);
61553                 list.selectAll('li:last-child input.key').node().focus();
61554             }, 0);
61555         }
61556     }
61557
61558
61559     rawTagEditor.state = function(_) {
61560         if (!arguments.length) return state;
61561         state = _;
61562         return rawTagEditor;
61563     };
61564
61565
61566     rawTagEditor.preset = function(_) {
61567         if (!arguments.length) return preset;
61568         preset = _;
61569         return rawTagEditor;
61570     };
61571
61572
61573     rawTagEditor.tags = function(_) {
61574         if (!arguments.length) return tags;
61575         tags = _;
61576         return rawTagEditor;
61577     };
61578
61579
61580     rawTagEditor.entityID = function(_) {
61581         if (!arguments.length) return id;
61582         id = _;
61583         return rawTagEditor;
61584     };
61585
61586
61587     return utilRebind(rawTagEditor, dispatch$$1, 'on');
61588 }
61589
61590 function uiFieldCheck(field) {
61591     var dispatch$$1 = dispatch('change'),
61592         options = field.strings && field.strings.options,
61593         values$$1 = [],
61594         texts = [],
61595         input = select(null),
61596         text$$1 = select(null),
61597         label = select(null),
61598         entity, value;
61599
61600     if (options) {
61601         for (var k in options) {
61602             values$$1.push(k === 'undefined' ? undefined : k);
61603             texts.push(field.t('options.' + k, { 'default': options[k] }));
61604         }
61605     } else {
61606         values$$1 = [undefined, 'yes'];
61607         texts = [t('inspector.unknown'), t('inspector.check.yes')];
61608         if (field.type === 'check') {
61609             values$$1.push('no');
61610             texts.push(t('inspector.check.no'));
61611         }
61612     }
61613
61614
61615     var check = function(selection$$1) {
61616         // hack: pretend oneway field is a oneway_yes field
61617         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
61618         if (field.id === 'oneway') {
61619             for (var key in entity.tags) {
61620                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
61621                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
61622                     break;
61623                 }
61624             }
61625         }
61626
61627         selection$$1.classed('checkselect', 'true');
61628
61629         label = selection$$1.selectAll('.preset-input-wrap')
61630             .data([0]);
61631
61632         var enter = label.enter()
61633             .append('label')
61634             .attr('class', 'preset-input-wrap');
61635
61636         enter
61637             .append('input')
61638             .property('indeterminate', field.type === 'check')
61639             .attr('type', 'checkbox')
61640             .attr('id', 'preset-input-' + field.id);
61641
61642         enter
61643             .append('span')
61644             .text(texts[0])
61645             .attr('class', 'value');
61646
61647         label = label.merge(enter);
61648         input = label.selectAll('input');
61649         text$$1 = label.selectAll('span.value');
61650
61651         input
61652             .on('click', function() {
61653                 var t$$1 = {};
61654                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
61655                 dispatch$$1.call('change', this, t$$1);
61656                 event.stopPropagation();
61657             });
61658     };
61659
61660
61661     check.entity = function(_) {
61662         if (!arguments.length) return entity;
61663         entity = _;
61664         return check;
61665     };
61666
61667
61668     check.tags = function(tags) {
61669         value = tags[field.key];
61670         input.property('indeterminate', field.type === 'check' && !value);
61671         input.property('checked', value === 'yes');
61672         text$$1.text(texts[values$$1.indexOf(value)]);
61673         label.classed('set', !!value);
61674     };
61675
61676
61677     check.focus = function() {
61678         input.node().focus();
61679     };
61680
61681     return utilRebind(check, dispatch$$1, 'on');
61682 }
61683
61684 function uiFieldCombo(field, context) {
61685     var dispatch$$1 = dispatch('change'),
61686         nominatim = services.geocoder,
61687         taginfo = services.taginfo,
61688         isMulti = (field.type === 'multiCombo'),
61689         isNetwork = (field.type === 'networkCombo'),
61690         optstrings = field.strings && field.strings.options,
61691         optarray = field.options,
61692         snake_case = (field.snake_case || (field.snake_case === undefined)),
61693         combobox = d3combobox().minItems(isMulti ? 1 : 2),
61694         comboData = [],
61695         multiData = [],
61696         container,
61697         input,
61698         entity,
61699         country;
61700
61701     // ensure multiCombo field.key ends with a ':'
61702     if (isMulti && field.key.match(/:$/) === null) {
61703         field.key += ':';
61704     }
61705
61706
61707     function snake(s) {
61708         return s.replace(/\s+/g, '_');
61709     }
61710
61711     function unsnake(s) {
61712         return s.replace(/_+/g, ' ');
61713     }
61714
61715     function clean(s) {
61716         return s.split(';')
61717             .map(function(s) { return s.trim(); })
61718             .join(';');
61719     }
61720
61721
61722     // returns the tag value for a display value
61723     // (for multiCombo, dval should be the key suffix, not the entire key)
61724     function tagValue(dval) {
61725         dval = clean(dval || '');
61726
61727         if (optstrings) {
61728             var match = lodash.find(comboData, function(o) {
61729                 return o.key && clean(o.value) === dval;
61730             });
61731             if (match) {
61732                 return match.key;
61733             }
61734         }
61735
61736         if (field.type === 'typeCombo' && !dval) {
61737             return 'yes';
61738         }
61739
61740         return (snake_case ? snake(dval) : dval) || undefined;
61741     }
61742
61743
61744     // returns the display value for a tag value
61745     // (for multiCombo, tval should be the key suffix, not the entire key)
61746     function displayValue(tval) {
61747         tval = tval || '';
61748
61749         if (optstrings) {
61750             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
61751             if (match) {
61752                 return match.value;
61753             }
61754         }
61755
61756         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
61757             return '';
61758         }
61759
61760         return snake_case ? unsnake(tval) : tval;
61761     }
61762
61763
61764     function objectDifference(a, b) {
61765         return lodash.reject(a, function(d1) {
61766             return lodash.some(b, function(d2) { return d1.value === d2.value; });
61767         });
61768     }
61769
61770
61771     function initCombo(selection$$1, attachTo) {
61772         if (optstrings) {
61773             selection$$1.attr('readonly', 'readonly');
61774             selection$$1.call(combobox, attachTo);
61775             setStaticValues(setPlaceholder);
61776
61777         } else if (optarray) {
61778             selection$$1.call(combobox, attachTo);
61779             setStaticValues(setPlaceholder);
61780
61781         } else if (taginfo) {
61782             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
61783             setTaginfoValues('', setPlaceholder);
61784         }
61785     }
61786
61787
61788     function setStaticValues(callback) {
61789         if (!(optstrings || optarray)) return;
61790
61791         if (optstrings) {
61792             comboData = Object.keys(optstrings).map(function(k) {
61793                 var v = field.t('options.' + k, { 'default': optstrings[k] });
61794                 return {
61795                     key: k,
61796                     value: v,
61797                     title: v
61798                 };
61799             });
61800
61801         } else if (optarray) {
61802             comboData = optarray.map(function(k) {
61803                 var v = snake_case ? unsnake(k) : k;
61804                 return {
61805                     key: k,
61806                     value: v,
61807                     title: v
61808                 };
61809             });
61810         }
61811
61812         combobox.data(objectDifference(comboData, multiData));
61813         if (callback) callback(comboData);
61814     }
61815
61816
61817     function setTaginfoValues(q, callback) {
61818         var fn = isMulti ? 'multikeys' : 'values';
61819         var query = (isMulti ? field.key : '') + q;
61820         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
61821         if (hasCountryPrefix) {
61822             query = country + ':';
61823         }
61824         taginfo[fn]({
61825             debounce: true,
61826             key: field.key,
61827             geometry: context.geometry(entity.id),
61828             query: query
61829         }, function(err, data) {
61830             if (err) return;
61831             if (hasCountryPrefix) {
61832                 data = lodash.filter(data, function(d) {
61833                     return d.value.toLowerCase().indexOf(country + ':') === 0;
61834                 });
61835             }
61836             comboData = lodash.map(data, function(d) {
61837                 var k = d.value;
61838                 if (isMulti) k = k.replace(field.key, '');
61839                 var v = snake_case ? unsnake(k) : k;
61840                 return {
61841                     key: k,
61842                     value: v,
61843                     title: isMulti ? v : d.title
61844                 };
61845             });
61846             comboData = objectDifference(comboData, multiData);
61847             if (callback) callback(comboData);
61848         });
61849     }
61850
61851
61852     function setPlaceholder(d) {
61853         var ph;
61854         if (isMulti) {
61855             ph = field.placeholder() || t('inspector.add');
61856         } else {
61857             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
61858                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
61859             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
61860         }
61861
61862         container.selectAll('input')
61863             .attr('placeholder', ph + '…');
61864     }
61865
61866
61867     function change() {
61868         var val = tagValue(utilGetSetValue(input)),
61869             t$$1 = {};
61870
61871         if (isMulti) {
61872             if (!val) return;
61873             container.classed('active', false);
61874             utilGetSetValue(input, '');
61875             field.keys.push(field.key + val);
61876             t$$1[field.key + val] = 'yes';
61877             window.setTimeout(function() { input.node().focus(); }, 10);
61878
61879         } else {
61880             t$$1[field.key] = val;
61881         }
61882
61883         dispatch$$1.call('change', this, t$$1);
61884     }
61885
61886
61887     function removeMultikey(d) {
61888         event.stopPropagation();
61889         var t$$1 = {};
61890         t$$1[d.key] = undefined;
61891         dispatch$$1.call('change', this, t$$1);
61892     }
61893
61894
61895     function combo(selection$$1) {
61896         if (isMulti) {
61897             container = selection$$1.selectAll('ul').data([0]);
61898
61899             container = container.enter()
61900                 .append('ul')
61901                 .attr('class', 'form-field-multicombo')
61902                 .on('click', function() {
61903                     window.setTimeout(function() { input.node().focus(); }, 10);
61904                 })
61905                 .merge(container);
61906
61907         } else {
61908             container = selection$$1;
61909         }
61910
61911         input = container.selectAll('input')
61912             .data([0]);
61913
61914         input = input.enter()
61915             .append('input')
61916             .attr('type', 'text')
61917             .attr('id', 'preset-input-' + field.id)
61918             .call(initCombo, selection$$1)
61919             .merge(input);
61920
61921         if (isNetwork && nominatim && entity) {
61922             var center = entity.extent(context.graph()).center();
61923             nominatim.countryCode(center, function (err, code) {
61924                 country = code;
61925             });
61926         }
61927
61928         input
61929             .on('change', change)
61930             .on('blur', change);
61931
61932         if (isMulti) {
61933             combobox
61934                 .on('accept', function() {
61935                     input.node().blur();
61936                     input.node().focus();
61937                 });
61938
61939             input
61940                 .on('focus', function() { container.classed('active', true); });
61941         }
61942     }
61943
61944
61945     combo.tags = function(tags) {
61946         if (isMulti) {
61947             multiData = [];
61948
61949             // Build multiData array containing keys already set..
61950             Object.keys(tags).forEach(function(key) {
61951                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
61952
61953                 var suffix = key.substring(field.key.length);
61954                 multiData.push({
61955                     key: key,
61956                     value: displayValue(suffix)
61957                 });
61958             });
61959
61960             // Set keys for form-field modified (needed for undo and reset buttons)..
61961             field.keys = lodash.map(multiData, 'key');
61962
61963             // Exclude existing multikeys from combo options..
61964             var available = objectDifference(comboData, multiData);
61965             combobox.data(available);
61966
61967             // Hide 'Add' button if this field uses fixed set of
61968             // translateable optstrings and they're all currently used..
61969             container.selectAll('.combobox-input, .combobox-caret')
61970                 .classed('hide', optstrings && !available.length);
61971
61972
61973             // Render chips
61974             var chips = container.selectAll('.chips')
61975                 .data(multiData);
61976
61977             chips.exit()
61978                 .remove();
61979
61980             var enter = chips.enter()
61981                 .insert('li', 'input')
61982                 .attr('class', 'chips');
61983
61984             enter.append('span');
61985             enter.append('a');
61986
61987             chips = chips.merge(enter);
61988
61989             chips.select('span')
61990                 .text(function(d) { return d.value; });
61991
61992             chips.select('a')
61993                 .on('click', removeMultikey)
61994                 .attr('class', 'remove')
61995                 .text('×');
61996
61997         } else {
61998             utilGetSetValue(input, displayValue(tags[field.key]));
61999         }
62000     };
62001
62002
62003     combo.focus = function() {
62004         input.node().focus();
62005     };
62006
62007
62008     combo.entity = function(_) {
62009         if (!arguments.length) return entity;
62010         entity = _;
62011         return combo;
62012     };
62013
62014
62015     return utilRebind(combo, dispatch$$1, 'on');
62016 }
62017
62018 function uiFieldText(field, context) {
62019     var dispatch$$1 = dispatch('change'),
62020         nominatim = services.geocoder,
62021         input,
62022         entity;
62023
62024
62025     function i(selection$$1) {
62026         var fieldId = 'preset-input-' + field.id;
62027
62028         input = selection$$1.selectAll('input')
62029             .data([0]);
62030
62031         input = input.enter()
62032             .append('input')
62033             .attr('type', field.type)
62034             .attr('id', fieldId)
62035             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62036             .merge(input);
62037
62038         input
62039             .on('input', change(true))
62040             .on('blur', change())
62041             .on('change', change());
62042
62043         if (field.type === 'tel' && nominatim && entity) {
62044             var center = entity.extent(context.graph()).center();
62045             nominatim.countryCode(center, function (err, countryCode) {
62046                 if (err || !dataPhoneFormats[countryCode]) return;
62047                 selection$$1.selectAll('#' + fieldId)
62048                     .attr('placeholder', dataPhoneFormats[countryCode]);
62049             });
62050
62051         } else if (field.type === 'number') {
62052             input.attr('type', 'text');
62053
62054             var spinControl = selection$$1.selectAll('.spin-control')
62055                 .data([0]);
62056
62057             var enter = spinControl.enter()
62058                 .append('div')
62059                 .attr('class', 'spin-control');
62060
62061             enter
62062                 .append('button')
62063                 .datum(1)
62064                 .attr('class', 'increment')
62065                 .attr('tabindex', -1);
62066
62067             enter
62068                 .append('button')
62069                 .datum(-1)
62070                 .attr('class', 'decrement')
62071                 .attr('tabindex', -1);
62072
62073             spinControl = spinControl
62074                 .merge(enter);
62075
62076             spinControl.selectAll('button')
62077                 .on('click', function(d) {
62078                     event.preventDefault();
62079                     var num = parseInt(input.node().value || 0, 10);
62080                     if (!isNaN(num)) input.node().value = num + d;
62081                     change()();
62082                 });
62083         }
62084     }
62085
62086
62087     function change(onInput) {
62088         return function() {
62089             var t$$1 = {};
62090             t$$1[field.key] = utilGetSetValue(input) || undefined;
62091             dispatch$$1.call('change', this, t$$1, onInput);
62092         };
62093     }
62094
62095
62096     i.entity = function(_) {
62097         if (!arguments.length) return entity;
62098         entity = _;
62099         return i;
62100     };
62101
62102
62103     i.tags = function(tags) {
62104         utilGetSetValue(input, tags[field.key] || '');
62105     };
62106
62107
62108     i.focus = function() {
62109         var node = input.node();
62110         if (node) node.focus();
62111     };
62112
62113     return utilRebind(i, dispatch$$1, 'on');
62114 }
62115
62116 function uiFieldAccess(field) {
62117     var dispatch$$1 = dispatch('change'),
62118         items;
62119
62120     function access(selection$$1) {
62121         var wrap = selection$$1.selectAll('.preset-input-wrap')
62122             .data([0]);
62123
62124         wrap = wrap.enter()
62125             .append('div')
62126             .attr('class', 'cf preset-input-wrap')
62127             .append('ul')
62128             .merge(wrap);
62129
62130         var list = wrap.selectAll('ul')
62131             .data([0]);
62132
62133         list = list.enter()
62134             .append('ul')
62135             .merge(list);
62136
62137
62138         items = list.selectAll('li')
62139             .data(field.keys);
62140
62141         // Enter
62142         var enter = items.enter()
62143             .append('li')
62144             .attr('class', function(d) { return 'cf preset-access-' + d; });
62145
62146         enter
62147             .append('span')
62148             .attr('class', 'col6 label preset-label-access')
62149             .attr('for', function(d) { return 'preset-input-access-' + d; })
62150             .text(function(d) { return field.t('types.' + d); });
62151
62152         enter
62153             .append('div')
62154             .attr('class', 'col6 preset-input-access-wrap')
62155             .append('input')
62156             .attr('type', 'text')
62157             .attr('class', 'preset-input-access')
62158             .attr('id', function(d) { return 'preset-input-access-' + d; })
62159             .each(function(d) {
62160                 select(this)
62161                     .call(d3combobox()
62162                         .data(access.options(d)));
62163             });
62164
62165
62166         // Update
62167         items = items.merge(enter);
62168
62169         wrap.selectAll('.preset-input-access')
62170             .on('change', change)
62171             .on('blur', change);
62172     }
62173
62174
62175     function change(d) {
62176         var tag = {};
62177         tag[d] = utilGetSetValue(select(this)) || undefined;
62178         dispatch$$1.call('change', this, tag);
62179     }
62180
62181
62182     access.options = function(type) {
62183         var options = ['no', 'permissive', 'private', 'destination'];
62184
62185         if (type !== 'access') {
62186             options.unshift('yes');
62187             options.push('designated');
62188
62189             if (type === 'bicycle') {
62190                 options.push('dismount');
62191             }
62192         }
62193
62194         return options.map(function(option) {
62195             return {
62196                 title: field.t('options.' + option + '.description'),
62197                 value: option
62198             };
62199         });
62200     };
62201
62202
62203     var placeholders = {
62204         footway: {
62205             foot: 'designated',
62206             motor_vehicle: 'no'
62207         },
62208         steps: {
62209             foot: 'yes',
62210             motor_vehicle: 'no',
62211             bicycle: 'no',
62212             horse: 'no'
62213         },
62214         pedestrian: {
62215             foot: 'yes',
62216             motor_vehicle: 'no'
62217         },
62218         cycleway: {
62219             motor_vehicle: 'no',
62220             bicycle: 'designated'
62221         },
62222         bridleway: {
62223             motor_vehicle: 'no',
62224             horse: 'designated'
62225         },
62226         path: {
62227             foot: 'yes',
62228             motor_vehicle: 'no',
62229             bicycle: 'yes',
62230             horse: 'yes'
62231         },
62232         motorway: {
62233             foot: 'no',
62234             motor_vehicle: 'yes',
62235             bicycle: 'no',
62236             horse: 'no'
62237         },
62238         trunk: {
62239             motor_vehicle: 'yes'
62240         },
62241         primary: {
62242             foot: 'yes',
62243             motor_vehicle: 'yes',
62244             bicycle: 'yes',
62245             horse: 'yes'
62246         },
62247         secondary: {
62248             foot: 'yes',
62249             motor_vehicle: 'yes',
62250             bicycle: 'yes',
62251             horse: 'yes'
62252         },
62253         tertiary: {
62254             foot: 'yes',
62255             motor_vehicle: 'yes',
62256             bicycle: 'yes',
62257             horse: 'yes'
62258         },
62259         residential: {
62260             foot: 'yes',
62261             motor_vehicle: 'yes',
62262             bicycle: 'yes',
62263             horse: 'yes'
62264         },
62265         unclassified: {
62266             foot: 'yes',
62267             motor_vehicle: 'yes',
62268             bicycle: 'yes',
62269             horse: 'yes'
62270         },
62271         service: {
62272             foot: 'yes',
62273             motor_vehicle: 'yes',
62274             bicycle: 'yes',
62275             horse: 'yes'
62276         },
62277         motorway_link: {
62278             foot: 'no',
62279             motor_vehicle: 'yes',
62280             bicycle: 'no',
62281             horse: 'no'
62282         },
62283         trunk_link: {
62284             motor_vehicle: 'yes'
62285         },
62286         primary_link: {
62287             foot: 'yes',
62288             motor_vehicle: 'yes',
62289             bicycle: 'yes',
62290             horse: 'yes'
62291         },
62292         secondary_link: {
62293             foot: 'yes',
62294             motor_vehicle: 'yes',
62295             bicycle: 'yes',
62296             horse: 'yes'
62297         },
62298         tertiary_link: {
62299             foot: 'yes',
62300             motor_vehicle: 'yes',
62301             bicycle: 'yes',
62302             horse: 'yes'
62303         }
62304     };
62305
62306
62307     access.tags = function(tags) {
62308         utilGetSetValue(items.selectAll('.preset-input-access'),
62309             function(d) { return tags[d] || ''; })
62310             .attr('placeholder', function() {
62311                 return tags.access ? tags.access : field.placeholder();
62312             });
62313
62314         items.selectAll('#preset-input-access-access')
62315             .attr('placeholder', 'yes');
62316
62317         lodash.forEach(placeholders[tags.highway], function(v, k) {
62318             items.selectAll('#preset-input-access-' + k)
62319                 .attr('placeholder', function() { return (tags.access || v); });
62320         });
62321     };
62322
62323
62324     access.focus = function() {
62325         items.selectAll('.preset-input-access')
62326             .node().focus();
62327     };
62328
62329
62330     return utilRebind(access, dispatch$$1, 'on');
62331 }
62332
62333 function uiFieldAddress(field, context) {
62334     var dispatch$$1 = dispatch('init', 'change'),
62335         nominatim = services.geocoder,
62336         wrap = select(null),
62337         isInitialized = false,
62338         entity;
62339
62340     function getNearStreets() {
62341         var extent$$1 = entity.extent(context.graph()),
62342             l = extent$$1.center(),
62343             box = geoExtent$$1(l).padByMeters(200);
62344
62345         var streets = context.intersects(box)
62346             .filter(isAddressable)
62347             .map(function(d) {
62348                 var loc = context.projection([
62349                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
62350                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
62351                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
62352                 return {
62353                     title: d.tags.name,
62354                     value: d.tags.name,
62355                     dist: choice.distance
62356                 };
62357             })
62358             .sort(function(a, b) {
62359                 return a.dist - b.dist;
62360             });
62361
62362         return lodash.uniqBy(streets, 'value');
62363
62364         function isAddressable(d) {
62365             return d.tags.highway && d.tags.name && d.type === 'way';
62366         }
62367     }
62368
62369
62370     function getNearCities() {
62371         var extent$$1 = entity.extent(context.graph()),
62372             l = extent$$1.center(),
62373             box = geoExtent$$1(l).padByMeters(200);
62374
62375         var cities = context.intersects(box)
62376             .filter(isAddressable)
62377             .map(function(d) {
62378                 return {
62379                     title: d.tags['addr:city'] || d.tags.name,
62380                     value: d.tags['addr:city'] || d.tags.name,
62381                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62382                 };
62383             })
62384             .sort(function(a, b) {
62385                 return a.dist - b.dist;
62386             });
62387
62388         return lodash.uniqBy(cities, 'value');
62389
62390
62391         function isAddressable(d) {
62392             if (d.tags.name &&
62393                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
62394                 return true;
62395
62396             if (d.tags.place && d.tags.name && (
62397                     d.tags.place === 'city' ||
62398                     d.tags.place === 'town' ||
62399                     d.tags.place === 'village'))
62400                 return true;
62401
62402             if (d.tags['addr:city']) return true;
62403
62404             return false;
62405         }
62406     }
62407
62408     function getNearValues(key) {
62409         var extent$$1 = entity.extent(context.graph()),
62410             l = extent$$1.center(),
62411             box = geoExtent$$1(l).padByMeters(200);
62412
62413         var results = context.intersects(box)
62414             .filter(function hasTag(d) {
62415                 return d.tags[key];
62416             })
62417             .map(function(d) {
62418                 return {
62419                     title: d.tags[key],
62420                     value: d.tags[key],
62421                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62422                 };
62423             })
62424             .sort(function(a, b) {
62425                 return a.dist - b.dist;
62426             });
62427
62428         return lodash.uniqBy(results, 'value');
62429     }
62430
62431
62432     function initCallback(err, countryCode) {
62433         if (err) return;
62434
62435         var addressFormat = lodash.find(dataAddressFormats, function (a) {
62436             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
62437         }) || lodash.first(dataAddressFormats);
62438
62439         var widths = addressFormat.widths || {
62440             housenumber: 1/3, street: 2/3,
62441             city: 2/3, state: 1/4, postcode: 1/3
62442         };
62443
62444         function row(r) {
62445             // Normalize widths.
62446             var total = lodash.reduce(r, function(sum$$1, field) {
62447                 return sum$$1 + (widths[field] || 0.5);
62448             }, 0);
62449
62450             return r.map(function (field) {
62451                 return {
62452                     id: field,
62453                     width: (widths[field] || 0.5) / total
62454                 };
62455             });
62456         }
62457
62458         wrap.selectAll('div.addr-row')
62459             .data(addressFormat.format)
62460             .enter()
62461             .append('div')
62462             .attr('class', 'addr-row')
62463             .selectAll('input')
62464             .data(row)
62465             .enter()
62466             .append('input')
62467             .property('type', 'text')
62468             .attr('placeholder', function (d) {
62469                 var localkey = d.id + '!' + countryCode,
62470                     tkey = field.strings.placeholders[localkey] ? localkey : d.id;
62471                 return field.t('placeholders.' + tkey);
62472             })
62473             .attr('class', function (d) { return 'addr-' + d.id; })
62474             .style('width', function (d) { return d.width * 100 + '%'; });
62475
62476         // Update
62477
62478         // setup dropdowns for common address tags
62479         var dropdowns = addressFormat.dropdowns || [
62480             'city', 'county', 'country', 'district', 'hamlet',
62481             'neighbourhood', 'place', 'postcode', 'province',
62482             'quarter', 'state', 'street', 'subdistrict', 'suburb'
62483         ];
62484
62485         // If fields exist for any of these tags, create dropdowns to pick nearby values..
62486         dropdowns.forEach(function(tag) {
62487             var nearValues = (tag === 'street') ? getNearStreets
62488                     : (tag === 'city') ? getNearCities
62489                     : getNearValues;
62490
62491             wrap.selectAll('input.addr-' + tag)
62492                 .call(d3combobox()
62493                     .minItems(1)
62494                     .fetcher(function(value, callback) {
62495                         callback(nearValues('addr:' + tag));
62496                     }));
62497         });
62498
62499         wrap.selectAll('input')
62500             .on('blur', change())
62501             .on('change', change());
62502
62503         wrap.selectAll('input:not(.combobox-input)')
62504             .on('input', change(true));
62505
62506         dispatch$$1.call('init');
62507         isInitialized = true;
62508     }
62509
62510
62511     function address(selection$$1) {
62512         isInitialized = false;
62513
62514         wrap = selection$$1.selectAll('.preset-input-wrap')
62515             .data([0]);
62516
62517         wrap = wrap.enter()
62518             .append('div')
62519             .attr('class', 'preset-input-wrap')
62520             .merge(wrap);
62521
62522         if (nominatim && entity) {
62523             var center = entity.extent(context.graph()).center();
62524             nominatim.countryCode(center, initCallback);
62525         }
62526     }
62527
62528
62529     function change(onInput) {
62530         return function() {
62531             var tags = {};
62532
62533             wrap.selectAll('input')
62534                 .each(function (field) {
62535                     tags['addr:' + field.id] = this.value || undefined;
62536                 });
62537
62538             dispatch$$1.call('change', this, tags, onInput);
62539         };
62540     }
62541
62542
62543     function updateTags(tags) {
62544         utilGetSetValue(wrap.selectAll('input'), function (field) {
62545             return tags['addr:' + field.id] || '';
62546         });
62547     }
62548
62549
62550     address.entity = function(_) {
62551         if (!arguments.length) return entity;
62552         entity = _;
62553         return address;
62554     };
62555
62556
62557     address.tags = function(tags) {
62558         if (isInitialized) {
62559             updateTags(tags);
62560         } else {
62561             dispatch$$1.on('init', function () {
62562                 dispatch$$1.on('init', null);
62563                 updateTags(tags);
62564             });
62565         }
62566     };
62567
62568
62569     address.focus = function() {
62570         var node = wrap.selectAll('input').node();
62571         if (node) node.focus();
62572     };
62573
62574
62575     return utilRebind(address, dispatch$$1, 'on');
62576 }
62577
62578 function uiFieldCycleway(field) {
62579     var dispatch$$1 = dispatch('change'),
62580         items = select(null);
62581
62582
62583     function cycleway(selection$$1) {
62584
62585         function stripcolon(s) {
62586             return s.replace(':', '');
62587         }
62588
62589
62590         var wrap = selection$$1.selectAll('.preset-input-wrap')
62591             .data([0]);
62592
62593         wrap = wrap.enter()
62594             .append('div')
62595             .attr('class', 'cf preset-input-wrap')
62596             .merge(wrap);
62597
62598
62599         var div = wrap.selectAll('ul')
62600             .data([0]);
62601
62602         div = div.enter()
62603             .append('ul')
62604             .merge(div);
62605
62606
62607         items = div.selectAll('li')
62608             .data(field.keys);
62609
62610         var enter = items.enter()
62611             .append('li')
62612             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
62613
62614         enter
62615             .append('span')
62616             .attr('class', 'col6 label preset-label-cycleway')
62617             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
62618             .text(function(d) { return field.t('types.' + d); });
62619
62620         enter
62621             .append('div')
62622             .attr('class', 'col6 preset-input-cycleway-wrap')
62623             .append('input')
62624             .attr('type', 'text')
62625             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
62626             .each(function(d) {
62627                 select(this).call(d3combobox().data(cycleway.options(d)));
62628             });
62629
62630
62631         // Update
62632         wrap.selectAll('.preset-input-cycleway')
62633             .on('change', change)
62634             .on('blur', change);
62635     }
62636
62637
62638     function change() {
62639         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
62640             right = utilGetSetValue(select('.preset-input-cyclewayright')),
62641             tag = {};
62642
62643         if (left === 'none' || left === '') { left = undefined; }
62644         if (right === 'none' || right === '') { right = undefined; }
62645
62646         // Always set both left and right as changing one can affect the other
62647         tag = {
62648             cycleway: undefined,
62649             'cycleway:left': left,
62650             'cycleway:right': right
62651         };
62652
62653         // If the left and right tags match, use the cycleway tag to tag both
62654         // sides the same way
62655         if (left === right) {
62656             tag = {
62657                 cycleway: left,
62658                 'cycleway:left': undefined,
62659                 'cycleway:right': undefined
62660             };
62661         }
62662
62663         dispatch$$1.call('change', this, tag);
62664     }
62665
62666
62667     cycleway.options = function() {
62668         return keys(field.strings.options).map(function(option) {
62669             return {
62670                 title: field.t('options.' + option + '.description'),
62671                 value: option
62672             };
62673         });
62674     };
62675
62676
62677     cycleway.tags = function(tags) {
62678         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
62679                 // If cycleway is set, always return that
62680                 if (tags.cycleway) {
62681                     return tags.cycleway;
62682                 }
62683                 return tags[d] || '';
62684             })
62685             .attr('placeholder', field.placeholder());
62686     };
62687
62688
62689     cycleway.focus = function() {
62690         items.selectAll('.preset-input-cycleway')
62691             .node().focus();
62692     };
62693
62694
62695     return utilRebind(cycleway, dispatch$$1, 'on');
62696 }
62697
62698 function uiFieldLanes(field, context) {
62699     var dispatch$$1 = dispatch('change'),
62700         LANE_WIDTH = 40,
62701         LANE_HEIGHT = 200,
62702         wayID,
62703         lanesData;
62704
62705     function lanes(selection$$1) {
62706         lanesData = context.entity(wayID).lanes();
62707
62708         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62709             selection$$1.call(lanes.off);
62710             return;
62711         }
62712
62713         var wrap = selection$$1.selectAll('.preset-input-wrap')
62714             .data([0]);
62715
62716         wrap = wrap.enter()
62717             .append('div')
62718             .attr('class', 'preset-input-wrap')
62719             .merge(wrap);
62720
62721         var surface =  wrap.selectAll('.surface')
62722             .data([0]);
62723
62724         var d = utilGetDimensions(wrap);
62725         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
62726
62727         surface = surface.enter()
62728             .append('svg')
62729             .attr('width', d[0])
62730             .attr('height', 300)
62731             .attr('class', 'surface')
62732             .merge(surface);
62733
62734
62735         var lanesSelection = surface.selectAll('.lanes')
62736             .data([0]);
62737
62738         lanesSelection = lanesSelection.enter()
62739             .append('g')
62740             .attr('class', 'lanes')
62741             .merge(lanesSelection);
62742
62743         lanesSelection
62744             .attr('transform', function () {
62745                 return 'translate(' + (freeSpace / 2) + ', 0)';
62746             });
62747
62748
62749         var lane = lanesSelection.selectAll('.lane')
62750            .data(lanesData.lanes);
62751
62752         lane.exit()
62753             .remove();
62754
62755         var enter = lane.enter()
62756             .append('g')
62757             .attr('class', 'lane');
62758
62759         enter
62760             .append('g')
62761             .append('rect')
62762             .attr('y', 50)
62763             .attr('width', LANE_WIDTH)
62764             .attr('height', LANE_HEIGHT);
62765
62766         enter
62767             .append('g')
62768             .attr('class', 'forward')
62769             .append('text')
62770             .attr('y', 40)
62771             .attr('x', 14)
62772             .text('▲');
62773
62774         enter
62775             .append('g')
62776             .attr('class', 'bothways')
62777             .append('text')
62778             .attr('y', 40)
62779             .attr('x', 14)
62780             .text('▲▼');
62781
62782         enter
62783             .append('g')
62784             .attr('class', 'backward')
62785             .append('text')
62786             .attr('y', 40)
62787             .attr('x', 14)
62788             .text('▼');
62789
62790
62791         lane = lane
62792             .merge(enter);
62793
62794         lane
62795             .attr('transform', function(d) {
62796                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
62797             });
62798
62799         lane.select('.forward')
62800             .style('visibility', function(d) {
62801                 return d.direction === 'forward' ? 'visible' : 'hidden';
62802             });
62803
62804         lane.select('.bothways')
62805             .style('visibility', function(d) {
62806                 return d.direction === 'bothways' ? 'visible' : 'hidden';
62807             });
62808
62809         lane.select('.backward')
62810             .style('visibility', function(d) {
62811                 return d.direction === 'backward' ? 'visible' : 'hidden';
62812             });
62813     }
62814
62815
62816     lanes.entity = function(_) {
62817         if (!wayID || wayID !== _.id) {
62818             wayID = _.id;
62819         }
62820     };
62821
62822     lanes.tags = function() {};
62823     lanes.focus = function() {};
62824     lanes.off = function() {};
62825
62826     return utilRebind(lanes, dispatch$$1, 'on');
62827 }
62828
62829 function uiFieldLocalized(field, context) {
62830     var dispatch$$1 = dispatch('change', 'input'),
62831         wikipedia = services.wikipedia,
62832         input = select(null),
62833         localizedInputs = select(null),
62834         wikiTitles,
62835         entity;
62836
62837
62838     function localized(selection$$1) {
62839         input = selection$$1.selectAll('.localized-main')
62840             .data([0]);
62841
62842         input = input.enter()
62843             .append('input')
62844             .attr('type', 'text')
62845             .attr('id', 'preset-input-' + field.id)
62846             .attr('class', 'localized-main')
62847             .attr('placeholder', field.placeholder())
62848             .merge(input);
62849
62850         if (field.id === 'name') {
62851             var preset = context.presets().match(entity, context.graph());
62852             input.call(d3combobox().fetcher(
62853                 utilSuggestNames(preset, dataSuggestions)
62854             ));
62855         }
62856
62857         input
62858             .on('input', change(true))
62859             .on('blur', change())
62860             .on('change', change());
62861
62862
62863         var translateButton = selection$$1.selectAll('.localized-add')
62864             .data([0]);
62865
62866         translateButton = translateButton.enter()
62867             .append('button')
62868             .attr('class', 'button-input-action localized-add minor')
62869             .attr('tabindex', -1)
62870             .call(svgIcon('#icon-plus'))
62871             .call(tooltip()
62872                 .title(t('translate.translate'))
62873                 .placement('left'))
62874             .merge(translateButton);
62875
62876         translateButton
62877             .on('click', addNew);
62878
62879
62880         localizedInputs = selection$$1.selectAll('.localized-wrap')
62881             .data([0]);
62882
62883         localizedInputs = localizedInputs.enter().append('div')
62884             .attr('class', 'localized-wrap')
62885             .merge(localizedInputs);
62886     }
62887
62888
62889     function addNew() {
62890         event.preventDefault();
62891         var data$$1 = localizedInputs.selectAll('div.entry').data();
62892         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
62893         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
62894         var isLangEn = defaultLang.indexOf('en') > -1;
62895         if (isLangEn || langExists) {
62896             defaultLang = '';
62897         }
62898         data$$1.push({ lang: defaultLang, value: '' });
62899         localizedInputs.call(render, data$$1);
62900     }
62901
62902
62903     function change(onInput) {
62904         return function() {
62905             var t$$1 = {};
62906             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
62907             dispatch$$1.call('change', this, t$$1, onInput);
62908         };
62909     }
62910
62911
62912     function key(lang) {
62913         return field.key + ':' + lang;
62914     }
62915
62916
62917     function changeLang(d) {
62918         var lang = utilGetSetValue(select(this)),
62919             t$$1 = {},
62920             language = lodash.find(dataWikipedia, function(d) {
62921                 return d[0].toLowerCase() === lang.toLowerCase() ||
62922                     d[1].toLowerCase() === lang.toLowerCase();
62923             });
62924
62925         if (language) lang = language[2];
62926
62927         if (d.lang && d.lang !== lang) {
62928             t$$1[key(d.lang)] = undefined;
62929         }
62930
62931         var value = utilGetSetValue(select(this.parentNode)
62932             .selectAll('.localized-value'));
62933
62934         if (lang && value) {
62935             t$$1[key(lang)] = value;
62936         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
62937             t$$1[key(lang)] = wikiTitles[d.lang];
62938         }
62939
62940         d.lang = lang;
62941         dispatch$$1.call('change', this, t$$1);
62942     }
62943
62944
62945     function changeValue(d) {
62946         if (!d.lang) return;
62947         var t$$1 = {};
62948         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
62949         dispatch$$1.call('change', this, t$$1);
62950     }
62951
62952
62953     function fetcher(value, cb) {
62954         var v = value.toLowerCase();
62955
62956         cb(dataWikipedia.filter(function(d) {
62957             return d[0].toLowerCase().indexOf(v) >= 0 ||
62958             d[1].toLowerCase().indexOf(v) >= 0 ||
62959             d[2].toLowerCase().indexOf(v) >= 0;
62960         }).map(function(d) {
62961             return { value: d[1] };
62962         }));
62963     }
62964
62965
62966     function render(selection$$1, data$$1) {
62967         var wraps = selection$$1.selectAll('div.entry').
62968             data(data$$1, function(d) { return d.lang; });
62969
62970         wraps.exit()
62971             .transition()
62972             .duration(200)
62973             .style('max-height','0px')
62974             .style('opacity', '0')
62975             .style('top','-10px')
62976             .remove();
62977
62978         var innerWrap = wraps.enter()
62979             .insert('div', ':first-child');
62980
62981         innerWrap.attr('class', 'entry')
62982             .each(function() {
62983                 var wrap = select(this);
62984                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
62985
62986                 var label = wrap
62987                     .append('label')
62988                     .attr('class','form-label')
62989                     .text(t('translate.localized_translation_label'))
62990                     .attr('for','localized-lang');
62991
62992                 label
62993                     .append('button')
62994                     .attr('class', 'minor remove')
62995                     .on('click', function(d){
62996                         event.preventDefault();
62997                         var t$$1 = {};
62998                         t$$1[key(d.lang)] = undefined;
62999                         dispatch$$1.call('change', this, t$$1);
63000                         select(this.parentNode.parentNode)
63001                             .style('top','0')
63002                             .style('max-height','240px')
63003                             .transition()
63004                             .style('opacity', '0')
63005                             .style('max-height','0px')
63006                             .remove();
63007                     })
63008                     .call(svgIcon('#operation-delete'));
63009
63010                 wrap
63011                     .append('input')
63012                     .attr('class', 'localized-lang')
63013                     .attr('type', 'text')
63014                     .attr('placeholder',t('translate.localized_translation_language'))
63015                     .on('blur', changeLang)
63016                     .on('change', changeLang)
63017                     .call(langcombo);
63018
63019                 wrap
63020                     .append('input')
63021                     .on('blur', changeValue)
63022                     .on('change', changeValue)
63023                     .attr('type', 'text')
63024                     .attr('placeholder', t('translate.localized_translation_name'))
63025                     .attr('class', 'localized-value');
63026             });
63027
63028         innerWrap
63029             .style('margin-top', '0px')
63030             .style('max-height', '0px')
63031             .style('opacity', '0')
63032             .transition()
63033             .duration(200)
63034             .style('margin-top', '10px')
63035             .style('max-height', '240px')
63036             .style('opacity', '1')
63037             .on('end', function() {
63038                 select(this)
63039                     .style('max-height', '')
63040                     .style('overflow', 'visible');
63041             });
63042
63043
63044         var entry = selection$$1.selectAll('.entry');
63045
63046         utilGetSetValue(entry.select('.localized-lang'), function(d) {
63047                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
63048                 return lang ? lang[1] : d.lang;
63049             });
63050
63051         utilGetSetValue(entry.select('.localized-value'),
63052             function(d) { return d.value; });
63053     }
63054
63055
63056     localized.tags = function(tags) {
63057         // Fetch translations from wikipedia
63058         if (tags.wikipedia && !wikiTitles) {
63059             wikiTitles = {};
63060             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
63061             if (wm && wm[0] && wm[1]) {
63062                 wikipedia.translations(wm[1], wm[2], function(d) {
63063                     wikiTitles = d;
63064                 });
63065             }
63066         }
63067
63068         utilGetSetValue(input, tags[field.key] || '');
63069
63070         var postfixed = [], k, m;
63071         for (k in tags) {
63072             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
63073             if (m && m[1] === field.key && m[2]) {
63074                 postfixed.push({ lang: m[2], value: tags[k] });
63075             }
63076         }
63077
63078         localizedInputs.call(render, postfixed.reverse());
63079     };
63080
63081
63082     localized.focus = function() {
63083         input.node().focus();
63084     };
63085
63086
63087     localized.entity = function(_) {
63088         if (!arguments.length) return entity;
63089         entity = _;
63090         return localized;
63091     };
63092
63093     return utilRebind(localized, dispatch$$1, 'on');
63094 }
63095
63096 function uiFieldMaxspeed(field, context) {
63097     var dispatch$$1 = dispatch('change'),
63098         entity,
63099         isImperial,
63100         unitInput = select(null),
63101         input = select(null),
63102         combobox;
63103
63104     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
63105         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
63106
63107
63108     function maxspeed(selection$$1) {
63109         combobox = d3combobox();
63110         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
63111
63112         input = selection$$1.selectAll('#preset-input-' + field.id)
63113             .data([0]);
63114
63115         input = input.enter()
63116             .append('input')
63117             .attr('type', 'text')
63118             .attr('id', 'preset-input-' + field.id)
63119             .attr('placeholder', field.placeholder())
63120             .call(combobox)
63121             .merge(input);
63122
63123         input
63124             .on('change', change)
63125             .on('blur', change);
63126
63127         var childNodes = context.graph().childNodes(context.entity(entity.id)),
63128             loc = childNodes[~~(childNodes.length/2)].loc;
63129
63130         isImperial = lodash.some(dataImperial.features, function(f) {
63131             return lodash.some(f.geometry.coordinates, function(d) {
63132                 return geoPointInPolygon(loc, d);
63133             });
63134         });
63135
63136         unitInput = selection$$1.selectAll('input.maxspeed-unit')
63137             .data([0]);
63138
63139         unitInput = unitInput.enter()
63140             .append('input')
63141             .attr('type', 'text')
63142             .attr('class', 'maxspeed-unit')
63143             .call(unitCombobox)
63144             .merge(unitInput);
63145
63146         unitInput
63147             .on('blur', changeUnits)
63148             .on('change', changeUnits);
63149
63150
63151         function changeUnits() {
63152             isImperial = utilGetSetValue(unitInput) === 'mph';
63153             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63154             setSuggestions();
63155             change();
63156         }
63157     }
63158
63159
63160     function setSuggestions() {
63161         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
63162         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63163     }
63164
63165
63166     function comboValues(d) {
63167         return {
63168             value: d.toString(),
63169             title: d.toString()
63170         };
63171     }
63172
63173
63174     function change() {
63175         var tag = {},
63176             value = utilGetSetValue(input);
63177
63178         if (!value) {
63179             tag[field.key] = undefined;
63180         } else if (isNaN(value) || !isImperial) {
63181             tag[field.key] = value;
63182         } else {
63183             tag[field.key] = value + ' mph';
63184         }
63185
63186         dispatch$$1.call('change', this, tag);
63187     }
63188
63189
63190     maxspeed.tags = function(tags) {
63191         var value = tags[field.key];
63192
63193         if (value && value.indexOf('mph') >= 0) {
63194             value = parseInt(value, 10);
63195             isImperial = true;
63196         } else if (value) {
63197             isImperial = false;
63198         }
63199
63200         setSuggestions();
63201         utilGetSetValue(input, value || '');
63202     };
63203
63204
63205     maxspeed.focus = function() {
63206         input.node().focus();
63207     };
63208
63209
63210     maxspeed.entity = function(_) {
63211         entity = _;
63212     };
63213
63214
63215     return utilRebind(maxspeed, dispatch$$1, 'on');
63216 }
63217
63218 function uiFieldRadio(field) {
63219     var dispatch$$1 = dispatch('change'),
63220         placeholder = select(null),
63221         labels = select(null),
63222         radios = select(null);
63223
63224
63225     function radio(selection$$1) {
63226         selection$$1.classed('preset-radio', true);
63227
63228         var wrap = selection$$1.selectAll('.preset-input-wrap')
63229             .data([0]);
63230
63231         var enter = wrap.enter()
63232             .append('div')
63233             .attr('class', 'preset-input-wrap toggle-list');
63234
63235         enter
63236             .append('span')
63237             .attr('class', 'placeholder');
63238
63239         wrap = wrap
63240             .merge(enter);
63241
63242
63243         placeholder = wrap.selectAll('.placeholder');
63244
63245         labels = wrap.selectAll('label')
63246             .data(field.options || field.keys);
63247
63248         enter = labels.enter()
63249             .append('label');
63250
63251         enter.append('input')
63252             .attr('type', 'radio')
63253             .attr('name', field.id)
63254             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
63255             .attr('checked', false);
63256
63257         enter.append('span')
63258             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
63259
63260         labels = labels
63261             .merge(enter);
63262
63263         radios = labels.selectAll('input')
63264             .on('change', change);
63265     }
63266
63267
63268     function change() {
63269         var t$$1 = {};
63270         if (field.key) t$$1[field.key] = undefined;
63271         radios.each(function(d) {
63272             var active$$1 = select(this).property('checked');
63273             if (field.key) {
63274                 if (active$$1) t$$1[field.key] = d;
63275             } else {
63276                 t$$1[d] = active$$1 ? 'yes' : undefined;
63277             }
63278         });
63279         dispatch$$1.call('change', this, t$$1);
63280     }
63281
63282
63283     radio.tags = function(tags) {
63284         function checked(d) {
63285             if (field.key) {
63286                 return tags[field.key] === d;
63287             } else {
63288                 return !!(tags[d] && tags[d] !== 'no');
63289             }
63290         }
63291
63292         labels.classed('active', checked);
63293         radios.property('checked', checked);
63294         var selection$$1 = radios.filter(function() { return this.checked; });
63295         if (selection$$1.empty()) {
63296             placeholder.text(t('inspector.none'));
63297         } else {
63298             placeholder.text(selection$$1.attr('value'));
63299         }
63300     };
63301
63302
63303     radio.focus = function() {
63304         radios.node().focus();
63305     };
63306
63307
63308     return utilRebind(radio, dispatch$$1, 'on');
63309 }
63310
63311 function uiFieldRestrictions(field, context) {
63312     var dispatch$$1 = dispatch('change'),
63313         breathe = behaviorBreathe(context),
63314         hover = behaviorHover(context),
63315         initialized = false,
63316         vertexID,
63317         fromNodeID;
63318
63319
63320     function restrictions(selection$$1) {
63321         // if form field is hidden or has detached from dom, clean up.
63322         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
63323             selection$$1.call(restrictions.off);
63324             return;
63325         }
63326
63327         var wrap = selection$$1.selectAll('.preset-input-wrap')
63328             .data([0]);
63329
63330         var enter = wrap.enter()
63331             .append('div')
63332             .attr('class', 'preset-input-wrap');
63333
63334         enter
63335             .append('div')
63336             .attr('class', 'restriction-help');
63337
63338
63339         var intersection = osmIntersection(context.graph(), vertexID),
63340             graph = intersection.graph,
63341             vertex = graph.entity(vertexID),
63342             filter = utilFunctor(true),
63343             extent$$1 = geoExtent$$1(),
63344             projection = geoRawMercator();
63345
63346         var d = utilGetDimensions(wrap.merge(enter)),
63347             c = [d[0] / 2, d[1] / 2],
63348             z = 24;
63349
63350         projection
63351             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
63352
63353         var s = projection(vertex.loc);
63354
63355         projection
63356             .translate([c[0] - s[0], c[1] - s[1]])
63357             .clipExtent([[0, 0], d]);
63358
63359         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
63360             drawVertices = svgVertices$$1(projection, context),
63361             drawLines = svgLines$$1(projection, context),
63362             drawTurns = svgTurns(projection, context);
63363
63364         enter
63365             .call(drawLayers);
63366
63367         wrap = wrap
63368             .merge(enter);
63369
63370         var surface = wrap.selectAll('.surface');
63371
63372         if (!enter.empty()) {
63373             initialized = true;
63374             surface
63375                 .call(breathe)
63376                 .call(hover);
63377         }
63378
63379         surface
63380             .call(utilSetDimensions, d)
63381             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
63382             .call(drawLines, graph, intersection.ways, filter)
63383             .call(drawTurns, graph, intersection.turns(fromNodeID));
63384
63385         surface
63386             .on('click.restrictions', click)
63387             .on('mouseover.restrictions', mouseover)
63388             .on('mouseout.restrictions', mouseout);
63389
63390         surface
63391             .selectAll('.selected')
63392             .classed('selected', false);
63393
63394         if (fromNodeID) {
63395             surface
63396                 .selectAll('.' + intersection.highways[fromNodeID].id)
63397                 .classed('selected', true);
63398         }
63399
63400         mouseout();
63401
63402         context.history()
63403             .on('change.restrictions', render);
63404
63405         select(window)
63406             .on('resize.restrictions', function() {
63407                 utilSetDimensions(wrap, null);
63408                 render();
63409             });
63410
63411
63412         function click() {
63413             surface
63414                 .call(breathe.off)
63415                 .call(breathe);
63416
63417             var datum = event.target.__data__;
63418             if (datum instanceof osmEntity$$1) {
63419                 fromNodeID = intersection.adjacentNodeId(datum.id);
63420                 render();
63421             } else if (datum instanceof osmTurn) {
63422                 if (datum.restriction) {
63423                     context.perform(
63424                         actionUnrestrictTurn(datum, projection),
63425                         t('operations.restriction.annotation.delete')
63426                     );
63427                 } else {
63428                     context.perform(
63429                         actionRestrictTurn(datum, projection),
63430                         t('operations.restriction.annotation.create')
63431                     );
63432                 }
63433             }
63434         }
63435
63436
63437         function mouseover() {
63438             var datum = event.target.__data__;
63439             if (datum instanceof osmTurn) {
63440                 var graph = context.graph(),
63441                     presets = context.presets(),
63442                     preset;
63443
63444                 if (datum.restriction) {
63445                     preset = presets.match(graph.entity(datum.restriction), graph);
63446                 } else {
63447                     preset = presets.item('type/restriction/' +
63448                         osmInferRestriction(
63449                             graph,
63450                             datum.from,
63451                             datum.via,
63452                             datum.to,
63453                             projection
63454                         )
63455                     );
63456                 }
63457
63458                 wrap.selectAll('.restriction-help')
63459                     .text(t('operations.restriction.help.' +
63460                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
63461                         { restriction: preset.name() })
63462                     );
63463             }
63464         }
63465
63466
63467         function mouseout() {
63468             wrap.selectAll('.restriction-help')
63469                 .text(t('operations.restriction.help.' +
63470                     (fromNodeID ? 'toggle' : 'select'))
63471                 );
63472         }
63473
63474
63475         function render() {
63476             if (context.hasEntity(vertexID)) {
63477                 restrictions(selection$$1);
63478             }
63479         }
63480     }
63481
63482
63483     restrictions.entity = function(_) {
63484         if (!vertexID || vertexID !== _.id) {
63485             fromNodeID = null;
63486             vertexID = _.id;
63487         }
63488     };
63489
63490
63491     restrictions.tags = function() {};
63492     restrictions.focus = function() {};
63493
63494
63495     restrictions.off = function(selection$$1) {
63496         if (!initialized) return;
63497
63498         selection$$1.selectAll('.surface')
63499             .call(hover.off)
63500             .call(breathe.off)
63501             .on('click.restrictions', null)
63502             .on('mouseover.restrictions', null)
63503             .on('mouseout.restrictions', null);
63504
63505         context.history()
63506             .on('change.restrictions', null);
63507
63508         select(window)
63509             .on('resize.restrictions', null);
63510     };
63511
63512
63513     return utilRebind(restrictions, dispatch$$1, 'on');
63514 }
63515
63516 function uiFieldTextarea(field) {
63517     var dispatch$$1 = dispatch('change'),
63518         input = select(null);
63519
63520
63521     function textarea(selection$$1) {
63522         input = selection$$1.selectAll('textarea')
63523             .data([0]);
63524
63525         input = input.enter()
63526             .append('textarea')
63527             .attr('id', 'preset-input-' + field.id)
63528             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
63529             .attr('maxlength', 255)
63530             .on('input', change(true))
63531             .on('blur', change())
63532             .on('change', change())
63533             .merge(input);
63534     }
63535
63536
63537     function change(onInput) {
63538         return function() {
63539             var t$$1 = {};
63540             t$$1[field.key] = utilGetSetValue(input) || undefined;
63541             dispatch$$1.call('change', this, t$$1, onInput);
63542         };
63543     }
63544
63545
63546     textarea.tags = function(tags) {
63547         utilGetSetValue(input, tags[field.key] || '');
63548     };
63549
63550
63551     textarea.focus = function() {
63552         input.node().focus();
63553     };
63554
63555
63556     return utilRebind(textarea, dispatch$$1, 'on');
63557 }
63558
63559 function uiFieldWikipedia(field, context) {
63560     var dispatch$$1 = dispatch('change'),
63561         wikipedia = services.wikipedia,
63562         wikidata = services.wikidata,
63563         link = select(null),
63564         lang = select(null),
63565         title = select(null),
63566         entity;
63567
63568
63569     function wiki(selection$$1) {
63570         var langcombo = d3combobox()
63571             .fetcher(function(value, cb) {
63572                 var v = value.toLowerCase();
63573
63574                 cb(dataWikipedia.filter(function(d) {
63575                     return d[0].toLowerCase().indexOf(v) >= 0 ||
63576                         d[1].toLowerCase().indexOf(v) >= 0 ||
63577                         d[2].toLowerCase().indexOf(v) >= 0;
63578                 }).map(function(d) {
63579                     return { value: d[1] };
63580                 }));
63581             });
63582
63583         var titlecombo = d3combobox()
63584             .fetcher(function(value, cb) {
63585                 if (!value) {
63586                     value = context.entity(entity.id).tags.name || '';
63587                 }
63588
63589                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
63590                 searchfn(language()[2], value, function(query, data$$1) {
63591                     cb(data$$1.map(function(d) {
63592                         return { value: d };
63593                     }));
63594                 });
63595             });
63596
63597
63598         lang = selection$$1.selectAll('input.wiki-lang')
63599             .data([0]);
63600
63601         lang = lang.enter()
63602             .append('input')
63603             .attr('type', 'text')
63604             .attr('class', 'wiki-lang')
63605             .attr('placeholder', t('translate.localized_translation_language'))
63606             .merge(lang);
63607
63608         utilGetSetValue(lang, language()[1]);
63609
63610         lang
63611             .call(langcombo)
63612             .on('blur', changeLang)
63613             .on('change', changeLang);
63614
63615
63616         title = selection$$1.selectAll('input.wiki-title')
63617             .data([0]);
63618
63619         title = title.enter()
63620             .append('input')
63621             .attr('type', 'text')
63622             .attr('class', 'wiki-title')
63623             .attr('id', 'preset-input-' + field.id)
63624             .merge(title);
63625
63626         title
63627             .call(titlecombo)
63628             .on('blur', blur)
63629             .on('change', change);
63630
63631
63632         link = selection$$1.selectAll('a.wiki-link')
63633             .data([0]);
63634
63635         link = link.enter()
63636             .append('a')
63637             .attr('class', 'wiki-link button-input-action minor')
63638             .attr('tabindex', -1)
63639             .attr('target', '_blank')
63640             .call(svgIcon('#icon-out-link', 'inline'))
63641             .merge(link);
63642     }
63643
63644
63645     function language() {
63646         var value = utilGetSetValue(lang).toLowerCase();
63647         var locale = utilDetect().locale.toLowerCase();
63648         var localeLanguage;
63649         return lodash.find(dataWikipedia, function(d) {
63650             if (d[2] === locale) localeLanguage = d;
63651             return d[0].toLowerCase() === value ||
63652                 d[1].toLowerCase() === value ||
63653                 d[2] === value;
63654         }) || localeLanguage || ['English', 'English', 'en'];
63655     }
63656
63657
63658     function changeLang() {
63659         utilGetSetValue(lang, language()[1]);
63660         change(true);
63661     }
63662
63663
63664     function blur() {
63665         change(true);
63666     }
63667
63668
63669     function change(skipWikidata) {
63670         var value = utilGetSetValue(title),
63671             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
63672             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63673             anchor,
63674             syncTags = {};
63675
63676         if (l) {
63677             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
63678             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
63679             if (m[3]) {
63680                 try {
63681                     // Best-effort `anchordecode:` implementation
63682                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
63683                 } catch (e) {
63684                     anchor = decodeURIComponent(m[3]);
63685                 }
63686                 value += '#' + anchor.replace(/_/g, ' ');
63687             }
63688             value = value.slice(0, 1).toUpperCase() + value.slice(1);
63689             utilGetSetValue(lang, l[1]);
63690             utilGetSetValue(title, value);
63691         }
63692
63693         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
63694         if (!skipWikidata) {
63695             syncTags.wikidata = undefined;
63696         }
63697
63698         dispatch$$1.call('change', this, syncTags);
63699
63700
63701         if (skipWikidata || !value || !language()[2]) return;
63702
63703         // attempt asynchronous update of wikidata tag..
63704         var initEntityId = entity.id,
63705             initWikipedia = context.entity(initEntityId).tags.wikipedia;
63706
63707         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
63708             if (!data$$1 || !Object.keys(data$$1).length) return;
63709             var qids = Object.keys(data$$1);
63710
63711             // 1. most recent change was a tag change
63712             var annotation = t('operations.change_tags.annotation'),
63713                 currAnnotation = context.history().undoAnnotation();
63714             if (currAnnotation !== annotation) return;
63715
63716             // 2. same entity exists and still selected
63717             var selectedIds = context.selectedIDs(),
63718                 currEntityId = selectedIds.length > 0 && selectedIds[0];
63719             if (currEntityId !== initEntityId) return;
63720
63721             // 3. wikipedia value has not changed
63722             var currTags = lodash.clone(context.entity(currEntityId).tags);
63723             if (initWikipedia !== currTags.wikipedia) return;
63724
63725             // ok to coalesce the update of wikidata tag into the previous tag change
63726             currTags.wikidata = qids && lodash.find(qids, function(id) {
63727                 return id.match(/^Q\d+$/);
63728             });
63729
63730             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
63731             dispatch$$1.call('change', this, currTags);
63732         });
63733     }
63734
63735
63736     wiki.tags = function(tags) {
63737         var value = tags[field.key] || '',
63738             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
63739             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63740             anchor = m && m[3];
63741
63742         // value in correct format
63743         if (l) {
63744             utilGetSetValue(lang, l[1]);
63745             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
63746             if (anchor) {
63747                 try {
63748                     // Best-effort `anchorencode:` implementation
63749                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
63750                 } catch (e) {
63751                     anchor = anchor.replace(/ /g, '_');
63752                 }
63753             }
63754             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
63755                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
63756
63757         // unrecognized value format
63758         } else {
63759             utilGetSetValue(title, value);
63760             if (value && value !== '') {
63761                 utilGetSetValue(lang, '');
63762             }
63763             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
63764         }
63765     };
63766
63767
63768     wiki.entity = function(_) {
63769         if (!arguments.length) return entity;
63770         entity = _;
63771         return wiki;
63772     };
63773
63774
63775     wiki.focus = function() {
63776         title.node().focus();
63777     };
63778
63779
63780     return utilRebind(wiki, dispatch$$1, 'on');
63781 }
63782
63783 var uiFields = {
63784     access: uiFieldAccess,
63785     address: uiFieldAddress,
63786     check: uiFieldCheck,
63787     defaultcheck: uiFieldCheck,
63788     combo: uiFieldCombo,
63789     typeCombo: uiFieldCombo,
63790     multiCombo: uiFieldCombo,
63791     networkCombo: uiFieldCombo,
63792     cycleway: uiFieldCycleway,
63793     text: uiFieldText,
63794     url: uiFieldText,
63795     number: uiFieldText,
63796     email: uiFieldText,
63797     tel: uiFieldText,
63798     localized: uiFieldLocalized,
63799     lanes: uiFieldLanes,
63800     maxspeed: uiFieldMaxspeed,
63801     radio: uiFieldRadio,
63802     restrictions: uiFieldRestrictions,
63803     textarea: uiFieldTextarea,
63804     wikipedia: uiFieldWikipedia
63805 };
63806
63807 function uiPreset(context) {
63808     var dispatch$$1 = dispatch('change'),
63809         state,
63810         fieldsArr,
63811         preset,
63812         tags,
63813         id;
63814
63815
63816     // Field Constructor
63817     function UIField(field, entity, show) {
63818         field = lodash.clone(field);
63819
63820         field.input = uiFields[field.type](field, context)
63821             .on('change', function(t$$1, onInput) {
63822                 dispatch$$1.call('change', field, t$$1, onInput);
63823             });
63824
63825         if (field.input.entity) field.input.entity(entity);
63826
63827         field.keys = field.keys || [field.key];
63828
63829         field.show = show;
63830
63831         field.shown = function() {
63832             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
63833         };
63834
63835         field.modified = function() {
63836             var original = context.graph().base().entities[entity.id];
63837             return lodash.some(field.keys, function(key) {
63838                 return original ? tags[key] !== original.tags[key] : tags[key];
63839             });
63840         };
63841
63842         field.revert = function() {
63843             var original = context.graph().base().entities[entity.id],
63844                 t$$1 = {};
63845             field.keys.forEach(function(key) {
63846                 t$$1[key] = original ? original.tags[key] : undefined;
63847             });
63848             return t$$1;
63849         };
63850
63851         field.present = function() {
63852             return lodash.some(field.keys, function(key) {
63853                 return tags[key];
63854             });
63855         };
63856
63857         field.remove = function() {
63858             var t$$1 = {};
63859             field.keys.forEach(function(key) {
63860                 t$$1[key] = undefined;
63861             });
63862             return t$$1;
63863         };
63864
63865         return field;
63866     }
63867
63868
63869     function fieldKey(field) {
63870         return field.id;
63871     }
63872
63873
63874     function presets(selection$$1) {
63875         selection$$1.call(uiDisclosure()
63876             .title(t('inspector.all_fields'))
63877             .expanded(context.storage('preset_fields.expanded') !== 'false')
63878             .on('toggled', toggled)
63879             .content(content)
63880         );
63881
63882         function toggled(expanded) {
63883             context.storage('preset_fields.expanded', expanded);
63884         }
63885     }
63886
63887
63888     function content(selection$$1) {
63889         if (!fieldsArr) {
63890             var entity = context.entity(id),
63891                 geometry = context.geometry(id),
63892                 presets = context.presets();
63893
63894             fieldsArr = [];
63895
63896             if (presets.field('name')) {
63897                 fieldsArr.push(UIField(presets.field('name'), entity));
63898             }
63899
63900             preset.fields.forEach(function(field) {
63901                 if (field.matchGeometry(geometry)) {
63902                     fieldsArr.push(UIField(field, entity, true));
63903                 }
63904             });
63905
63906             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
63907                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
63908             }
63909
63910             presets.universal().forEach(function(field) {
63911                 if (preset.fields.indexOf(field) < 0) {
63912                     fieldsArr.push(UIField(field, entity));
63913                 }
63914             });
63915         }
63916
63917         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
63918             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
63919
63920
63921         var form = selection$$1.selectAll('.preset-form')
63922             .data([0]);
63923
63924         form = form.enter()
63925             .append('div')
63926             .attr('class', 'preset-form inspector-inner fillL3')
63927             .merge(form);
63928
63929
63930         var fields = form.selectAll('.form-field')
63931             .data(shown, fieldKey);
63932
63933         fields.exit()
63934             .remove();
63935
63936         // Enter
63937         var enter = fields.enter()
63938             .append('div')
63939             .attr('class', function(field) {
63940                 return 'form-field form-field-' + field.id;
63941             });
63942
63943         var label = enter
63944             .append('label')
63945             .attr('class', 'form-label')
63946             .attr('for', function(field) { return 'preset-input-' + field.id; })
63947             .text(function(field) { return field.label(); });
63948
63949         var wrap = label
63950             .append('div')
63951             .attr('class', 'form-label-button-wrap');
63952
63953         wrap.append('button')
63954             .attr('class', 'remove-icon')
63955             .attr('tabindex', -1)
63956             .call(svgIcon('#operation-delete'));
63957
63958         wrap.append('button')
63959             .attr('class', 'modified-icon')
63960             .attr('tabindex', -1)
63961             .call(
63962                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
63963             );
63964
63965
63966         // Update
63967         fields = fields
63968             .merge(enter);
63969
63970         fields.selectAll('.form-label-button-wrap .remove-icon')
63971             .on('click', remove);
63972
63973         fields.selectAll('.modified-icon')
63974             .on('click', revert);
63975
63976         fields
63977             .order()
63978             .classed('modified', function(field) { return field.modified(); })
63979             .classed('present', function(field) { return field.present(); })
63980             .each(function(field) {
63981                 var reference = uiTagReference(field.reference || { key: field.key }, context);
63982
63983                 if (state === 'hover') {
63984                     reference.showing(false);
63985                 }
63986
63987                 select(this)
63988                     .call(field.input)
63989                     .selectAll('input')
63990                     .on('keydown', function() {
63991                         // if user presses enter, and combobox is not active, accept edits..
63992                         if (event.keyCode === 13 && select('.combobox').empty()) {
63993                             context.enter(modeBrowse(context));
63994                         }
63995                     })
63996                     .call(reference.body)
63997                     .select('.form-label-button-wrap')
63998                     .call(reference.button);
63999
64000                 field.input.tags(tags);
64001             });
64002
64003         notShown = notShown.map(function(field) {
64004             return {
64005                 title: field.label(),
64006                 value: field.label(),
64007                 field: field
64008             };
64009         });
64010
64011
64012         var more = selection$$1.selectAll('.more-fields')
64013             .data((notShown.length > 0) ? [0] : []);
64014
64015         more.exit()
64016             .remove();
64017
64018         more = more.enter()
64019             .append('div')
64020             .attr('class', 'more-fields')
64021             .append('label')
64022             .text(t('inspector.add_fields'))
64023             .merge(more);
64024
64025
64026         var input = more.selectAll('.value')
64027             .data([0]);
64028
64029         input.exit()
64030             .remove();
64031
64032         input = input.enter()
64033             .append('input')
64034             .attr('class', 'value')
64035             .attr('type', 'text')
64036             .merge(input);
64037
64038         input
64039             .call(utilGetSetValue, '')
64040             .attr('placeholder', function() {
64041                 var placeholder = [];
64042                 for (var field in notShown) {
64043                     placeholder.push(notShown[field].title);
64044                 }
64045                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
64046             })
64047             .call(d3combobox().data(notShown)
64048                 .minItems(1)
64049                 .on('accept', show));
64050
64051
64052         function show(field) {
64053             field = field.field;
64054             field.show = true;
64055             content(selection$$1);
64056             field.input.focus();
64057         }
64058
64059
64060         function revert(field) {
64061             event.stopPropagation();
64062             event.preventDefault();
64063             dispatch$$1.call('change', field, field.revert());
64064         }
64065
64066
64067         function remove(field) {
64068             event.stopPropagation();
64069             event.preventDefault();
64070             dispatch$$1.call('change', field, field.remove());
64071         }
64072     }
64073
64074
64075     presets.preset = function(_) {
64076         if (!arguments.length) return preset;
64077         if (preset && preset.id === _.id) return presets;
64078         preset = _;
64079         fieldsArr = null;
64080         return presets;
64081     };
64082
64083
64084     presets.state = function(_) {
64085         if (!arguments.length) return state;
64086         state = _;
64087         return presets;
64088     };
64089
64090
64091     presets.tags = function(_) {
64092         if (!arguments.length) return tags;
64093         tags = _;
64094         // Don't reset fieldsArr here.
64095         return presets;
64096     };
64097
64098
64099     presets.entityID = function(_) {
64100         if (!arguments.length) return id;
64101         if (id === _) return presets;
64102         id = _;
64103         fieldsArr = null;
64104         return presets;
64105     };
64106
64107
64108     return utilRebind(presets, dispatch$$1, 'on');
64109 }
64110
64111 function uiEntityEditor(context) {
64112     var dispatch$$1 = dispatch('choose'),
64113         state = 'select',
64114         coalesceChanges = false,
64115         modified = false,
64116         base,
64117         id,
64118         activePreset,
64119         reference;
64120
64121     var presetEditor = uiPreset(context)
64122         .on('change', changeTags);
64123     var rawTagEditor = uiRawTagEditor(context)
64124         .on('change', changeTags);
64125
64126
64127     function entityEditor(selection$$1) {
64128         var entity = context.entity(id),
64129             tags = lodash.clone(entity.tags);
64130
64131         // Header
64132         var header = selection$$1.selectAll('.header')
64133             .data([0]);
64134
64135         // Enter
64136         var enter = header.enter()
64137             .append('div')
64138             .attr('class', 'header fillL cf');
64139
64140         enter
64141             .append('button')
64142             .attr('class', 'fl preset-reset preset-choose')
64143             .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
64144
64145         enter
64146             .append('button')
64147             .attr('class', 'fr preset-close')
64148             .on('click', function() { context.enter(modeBrowse(context)); })
64149             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
64150
64151         enter
64152             .append('h3')
64153             .text(t('inspector.edit'));
64154
64155         // Update
64156         header = header
64157             .merge(enter);
64158
64159         header.selectAll('.preset-reset')
64160             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64161
64162
64163         // Body
64164         var body = selection$$1.selectAll('.inspector-body')
64165             .data([0]);
64166
64167         // Enter
64168         enter = body.enter()
64169             .append('div')
64170             .attr('class', 'inspector-body');
64171
64172         enter
64173             .append('div')
64174             .attr('class', 'preset-list-item inspector-inner')
64175             .append('div')
64176             .attr('class', 'preset-list-button-wrap')
64177             .append('button')
64178             .attr('class', 'preset-list-button preset-reset')
64179             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
64180             .append('div')
64181             .attr('class', 'label');
64182
64183         enter
64184             .append('div')
64185             .attr('class', 'inspector-border inspector-preset');
64186
64187         enter
64188             .append('div')
64189             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
64190
64191         enter
64192             .append('div')
64193             .attr('class', 'inspector-border raw-member-editor inspector-inner');
64194
64195         enter
64196             .append('div')
64197             .attr('class', 'raw-membership-editor inspector-inner');
64198
64199         // Update
64200         body = body
64201             .merge(enter);
64202
64203         body.selectAll('.preset-list-button-wrap')
64204             .call(reference.button);
64205
64206         body.selectAll('.preset-list-item')
64207             .call(reference.body);
64208
64209         body.selectAll('.preset-reset')
64210             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64211
64212         body.select('.preset-list-item button')
64213             .call(uiPresetIcon()
64214                 .geometry(context.geometry(id))
64215                 .preset(activePreset));
64216
64217         body.select('.preset-list-item .label')
64218             .text(activePreset.name());
64219
64220         body.select('.inspector-preset')
64221             .call(presetEditor
64222                 .preset(activePreset)
64223                 .entityID(id)
64224                 .tags(tags)
64225                 .state(state));
64226
64227         body.select('.raw-tag-editor')
64228             .call(rawTagEditor
64229                 .preset(activePreset)
64230                 .entityID(id)
64231                 .tags(tags)
64232                 .state(state));
64233
64234         if (entity.type === 'relation') {
64235             body.select('.raw-member-editor')
64236                 .style('display', 'block')
64237                 .call(uiRawMemberEditor(context)
64238                     .entityID(id));
64239         } else {
64240             body.select('.raw-member-editor')
64241                 .style('display', 'none');
64242         }
64243
64244         body.select('.raw-membership-editor')
64245             .call(uiRawMembershipEditor(context)
64246                 .entityID(id));
64247
64248
64249         context.history()
64250             .on('change.entity-editor', historyChanged);
64251
64252
64253         function historyChanged() {
64254             if (state === 'hide') return;
64255
64256             var entity = context.hasEntity(id),
64257                 graph = context.graph();
64258             if (!entity) return;
64259
64260             entityEditor.preset(context.presets().match(entity, graph));
64261             entityEditor.modified(base !== graph);
64262             entityEditor(selection$$1);
64263         }
64264     }
64265
64266
64267     function clean(o) {
64268
64269         function cleanVal(k, v) {
64270             function keepSpaces(k) {
64271                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
64272                     'operating_times', 'smoking_hours', 'happy_hours'];
64273                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
64274             }
64275
64276             var blacklist = ['description', 'note', 'fixme'];
64277             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
64278
64279             var cleaned = v.split(';')
64280                 .map(function(s) { return s.trim(); })
64281                 .join(keepSpaces(k) ? '; ' : ';');
64282
64283             // The code below is not intended to validate websites and emails.
64284             // It is only intended to prevent obvious copy-paste errors. (#2323)
64285
64286             // clean website- and email-like tags
64287             if (k.indexOf('website') !== -1 ||
64288                 k.indexOf('email') !== -1 ||
64289                 cleaned.indexOf('http') === 0) {
64290                 cleaned = cleaned
64291                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
64292
64293             }
64294
64295             return cleaned;
64296         }
64297
64298         var out = {}, k, v;
64299         for (k in o) {
64300             if (k && (v = o[k]) !== undefined) {
64301                 out[k] = cleanVal(k, v);
64302             }
64303         }
64304         return out;
64305     }
64306
64307
64308     // Tag changes that fire on input can all get coalesced into a single
64309     // history operation when the user leaves the field.  #2342
64310     function changeTags(changed, onInput) {
64311         var entity = context.entity(id),
64312             annotation = t('operations.change_tags.annotation'),
64313             tags = lodash.clone(entity.tags);
64314
64315         lodash.forEach(changed, function(v, k) {
64316             if (v !== undefined || tags.hasOwnProperty(k)) {
64317                 tags[k] = v;
64318             }
64319         });
64320
64321         if (!onInput) {
64322             tags = clean(tags);
64323         }
64324
64325         if (!lodash.isEqual(entity.tags, tags)) {
64326             if (coalesceChanges) {
64327                 context.overwrite(actionChangeTags(id, tags), annotation);
64328             } else {
64329                 context.perform(actionChangeTags(id, tags), annotation);
64330                 coalesceChanges = !!onInput;
64331             }
64332         }
64333     }
64334
64335
64336     entityEditor.modified = function(_) {
64337         if (!arguments.length) return modified;
64338         modified = _;
64339         selectAll('button.preset-close use')
64340             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
64341     };
64342
64343
64344     entityEditor.state = function(_) {
64345         if (!arguments.length) return state;
64346         state = _;
64347         return entityEditor;
64348     };
64349
64350
64351     entityEditor.entityID = function(_) {
64352         if (!arguments.length) return id;
64353         id = _;
64354         base = context.graph();
64355         entityEditor.preset(context.presets().match(context.entity(id), base));
64356         entityEditor.modified(false);
64357         coalesceChanges = false;
64358         return entityEditor;
64359     };
64360
64361
64362     entityEditor.preset = function(_) {
64363         if (!arguments.length) return activePreset;
64364         if (_ !== activePreset) {
64365             activePreset = _;
64366             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
64367                 .showing(false);
64368         }
64369         return entityEditor;
64370     };
64371
64372
64373     return utilRebind(entityEditor, dispatch$$1, 'on');
64374 }
64375
64376 function uiPresetList(context) {
64377     var dispatch$$1 = dispatch('choose'),
64378         id,
64379         currentPreset,
64380         autofocus = false;
64381
64382
64383     function presetList(selection$$1) {
64384         var entity = context.entity(id),
64385             geometry = context.geometry(id);
64386
64387         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
64388         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
64389             geometry = 'point';
64390         }
64391
64392         var presets = context.presets().matchGeometry(geometry);
64393
64394         selection$$1.html('');
64395
64396         var messagewrap = selection$$1
64397             .append('div')
64398             .attr('class', 'header fillL cf');
64399
64400         var message = messagewrap
64401             .append('h3')
64402             .text(t('inspector.choose'));
64403
64404         if (context.entity(id).isUsed(context.graph())) {
64405             messagewrap
64406                 .append('button')
64407                 .attr('class', 'preset-choose')
64408                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
64409                 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
64410         } else {
64411             messagewrap
64412                 .append('button')
64413                 .attr('class', 'close')
64414                 .on('click', function() {
64415                     context.enter(modeBrowse(context));
64416                 })
64417                 .call(svgIcon('#icon-close'));
64418         }
64419
64420         function keydown() {
64421             // hack to let delete shortcut work when search is autofocused
64422             if (search.property('value').length === 0 &&
64423                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
64424                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
64425                 event.preventDefault();
64426                 event.stopPropagation();
64427                 operationDelete([id], context)();
64428             } else if (search.property('value').length === 0 &&
64429                 (event.ctrlKey || event.metaKey) &&
64430                 event.keyCode === d3keybinding.keyCodes.z) {
64431                 event.preventDefault();
64432                 event.stopPropagation();
64433                 context.undo();
64434             } else if (!event.ctrlKey && !event.metaKey) {
64435                 select(this).on('keydown', null);
64436             }
64437         }
64438
64439         function keypress() {
64440             // enter
64441             var value = search.property('value');
64442             if (event.keyCode === 13 && value.length) {
64443                 list.selectAll('.preset-list-item:first-child').datum().choose();
64444             }
64445         }
64446
64447         function inputevent() {
64448             var value = search.property('value');
64449             list.classed('filtered', value.length);
64450             if (value.length) {
64451                 var results = presets.search(value, geometry);
64452                 message.text(t('inspector.results', {
64453                     n: results.collection.length,
64454                     search: value
64455                 }));
64456                 list.call(drawList, results);
64457             } else {
64458                 list.call(drawList, context.presets().defaults(geometry, 36));
64459                 message.text(t('inspector.choose'));
64460             }
64461         }
64462
64463         var searchWrap = selection$$1
64464             .append('div')
64465             .attr('class', 'search-header');
64466
64467         var search = searchWrap
64468             .append('input')
64469             .attr('class', 'preset-search-input')
64470             .attr('placeholder', t('inspector.search'))
64471             .attr('type', 'search')
64472             .on('keydown', keydown)
64473             .on('keypress', keypress)
64474             .on('input', inputevent);
64475
64476         searchWrap
64477             .call(svgIcon('#icon-search', 'pre-text'));
64478
64479         if (autofocus) {
64480             search.node().focus();
64481         }
64482
64483         var listWrap = selection$$1
64484             .append('div')
64485             .attr('class', 'inspector-body');
64486
64487         var list = listWrap
64488             .append('div')
64489             .attr('class', 'preset-list fillL cf')
64490             .call(drawList, context.presets().defaults(geometry, 36));
64491     }
64492
64493
64494     function drawList(list, presets) {
64495         var collection = presets.collection.map(function(preset) {
64496             return preset.members ? CategoryItem(preset) : PresetItem(preset);
64497         });
64498
64499         var items = list.selectAll('.preset-list-item')
64500             .data(collection, function(d) { return d.preset.id; });
64501
64502         items.order();
64503
64504         items.exit()
64505             .remove();
64506
64507         items.enter()
64508             .append('div')
64509             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
64510             .classed('current', function(item) { return item.preset === currentPreset; })
64511             .each(function(item) { select(this).call(item); })
64512             .style('opacity', 0)
64513             .transition()
64514             .style('opacity', 1);
64515     }
64516
64517
64518     function CategoryItem(preset) {
64519         var box, sublist, shown = false;
64520
64521         function item(selection$$1) {
64522             var wrap = selection$$1.append('div')
64523                 .attr('class', 'preset-list-button-wrap category col12');
64524
64525             var button = wrap
64526                 .append('button')
64527                 .attr('class', 'preset-list-button')
64528                 .classed('expanded', false)
64529                 .call(uiPresetIcon()
64530                     .geometry(context.geometry(id))
64531                     .preset(preset))
64532                 .on('click', function() {
64533                     var isExpanded = select(this).classed('expanded');
64534                     var iconName = isExpanded ?
64535                         (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
64536                     select(this)
64537                         .classed('expanded', !isExpanded);
64538                     select(this).selectAll('div.label svg.icon use')
64539                         .attr('href', iconName);
64540                     item.choose();
64541                 });
64542
64543             var label = button
64544                 .append('div')
64545                 .attr('class', 'label');
64546
64547             label
64548                 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
64549                 .append('span')
64550                 .html(function() { return preset.name() + '&hellip;'; });
64551
64552             box = selection$$1.append('div')
64553                 .attr('class', 'subgrid col12')
64554                 .style('max-height', '0px')
64555                 .style('opacity', 0);
64556
64557             box.append('div')
64558                 .attr('class', 'arrow');
64559
64560             sublist = box.append('div')
64561                 .attr('class', 'preset-list fillL3 cf fl');
64562         }
64563
64564
64565         item.choose = function() {
64566             if (!box || !sublist) return;
64567
64568             if (shown) {
64569                 shown = false;
64570                 box.transition()
64571                     .duration(200)
64572                     .style('opacity', '0')
64573                     .style('max-height', '0px')
64574                     .style('padding-bottom', '0px');
64575             } else {
64576                 shown = true;
64577                 sublist.call(drawList, preset.members);
64578                 box.transition()
64579                     .duration(200)
64580                     .style('opacity', '1')
64581                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
64582                     .style('padding-bottom', '20px');
64583             }
64584         };
64585
64586         item.preset = preset;
64587
64588         return item;
64589     }
64590
64591
64592     function PresetItem(preset) {
64593         function item(selection$$1) {
64594             var wrap = selection$$1.append('div')
64595                 .attr('class', 'preset-list-button-wrap col12');
64596
64597             wrap.append('button')
64598                 .attr('class', 'preset-list-button')
64599                 .call(uiPresetIcon()
64600                     .geometry(context.geometry(id))
64601                     .preset(preset))
64602                 .on('click', item.choose)
64603                 .append('div')
64604                 .attr('class', 'label')
64605                 .text(preset.name());
64606
64607             wrap.call(item.reference.button);
64608             selection$$1.call(item.reference.body);
64609         }
64610
64611         item.choose = function() {
64612             context.presets().choose(preset);
64613
64614             context.perform(
64615                 actionChangePreset(id, currentPreset, preset),
64616                 t('operations.change_tags.annotation')
64617             );
64618
64619             dispatch$$1.call('choose', this, preset);
64620         };
64621
64622         item.help = function() {
64623             event.stopPropagation();
64624             item.reference.toggle();
64625         };
64626
64627         item.preset = preset;
64628         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
64629
64630         return item;
64631     }
64632
64633
64634     presetList.autofocus = function(_) {
64635         if (!arguments.length) return autofocus;
64636         autofocus = _;
64637         return presetList;
64638     };
64639
64640
64641     presetList.entityID = function(_) {
64642         if (!arguments.length) return id;
64643         id = _;
64644         presetList.preset(context.presets().match(context.entity(id), context.graph()));
64645         return presetList;
64646     };
64647
64648
64649     presetList.preset = function(_) {
64650         if (!arguments.length) return currentPreset;
64651         currentPreset = _;
64652         return presetList;
64653     };
64654
64655
64656     return utilRebind(presetList, dispatch$$1, 'on');
64657 }
64658
64659 function uiViewOnOSM(context) {
64660     var id;
64661
64662     function viewOnOSM(selection) {
64663         var entity = context.entity(id);
64664
64665         selection.style('display', entity.isNew() ? 'none' : null);
64666
64667         var link = selection.selectAll('.view-on-osm')
64668             .data([0]);
64669
64670         var enter = link.enter()
64671             .append('a')
64672             .attr('class', 'view-on-osm')
64673             .attr('target', '_blank')
64674             .call(svgIcon('#icon-out-link', 'inline'));
64675
64676         enter
64677             .append('span')
64678             .text(t('inspector.view_on_osm'));
64679
64680         link
64681             .merge(enter)
64682             .attr('href', context.connection().entityURL(entity));
64683     }
64684
64685
64686     viewOnOSM.entityID = function(_) {
64687         if (!arguments.length) return id;
64688         id = _;
64689         return viewOnOSM;
64690     };
64691
64692     return viewOnOSM;
64693 }
64694
64695 function uiInspector(context) {
64696     var presetList = uiPresetList(context),
64697         entityEditor = uiEntityEditor(context),
64698         state = 'select',
64699         entityID,
64700         newFeature = false;
64701
64702
64703     function inspector(selection$$1) {
64704         presetList
64705             .entityID(entityID)
64706             .autofocus(newFeature)
64707             .on('choose', setPreset);
64708
64709         entityEditor
64710             .state(state)
64711             .entityID(entityID)
64712             .on('choose', showList);
64713
64714         var wrap = selection$$1.selectAll('.panewrap')
64715             .data([0]);
64716
64717         var enter = wrap.enter()
64718             .append('div')
64719             .attr('class', 'panewrap');
64720
64721         enter
64722             .append('div')
64723             .attr('class', 'preset-list-pane pane');
64724
64725         enter
64726             .append('div')
64727             .attr('class', 'entity-editor-pane pane');
64728
64729         wrap = wrap.merge(enter);
64730         var presetPane = wrap.selectAll('.preset-list-pane');
64731         var editorPane = wrap.selectAll('.entity-editor-pane');
64732
64733         var graph = context.graph(),
64734             entity = context.entity(entityID),
64735             showEditor = state === 'hover' ||
64736                 entity.isUsed(graph) ||
64737                 entity.isHighwayIntersection(graph);
64738
64739         if (showEditor) {
64740             wrap.style('right', '0%');
64741             editorPane.call(entityEditor);
64742         } else {
64743             wrap.style('right', '-100%');
64744             presetPane.call(presetList);
64745         }
64746
64747         var footer = selection$$1.selectAll('.footer')
64748             .data([0]);
64749
64750         footer = footer.enter()
64751             .append('div')
64752             .attr('class', 'footer')
64753             .merge(footer);
64754
64755         footer
64756             .call(uiViewOnOSM(context).entityID(entityID));
64757
64758
64759         function showList(preset) {
64760             wrap.transition()
64761                 .styleTween('right', function() { return value$1('0%', '-100%'); });
64762
64763             presetPane
64764                 .call(presetList.preset(preset).autofocus(true));
64765         }
64766
64767
64768         function setPreset(preset) {
64769             wrap.transition()
64770                 .styleTween('right', function() { return value$1('-100%', '0%'); });
64771
64772             editorPane
64773                 .call(entityEditor.preset(preset));
64774         }
64775     }
64776
64777
64778     inspector.state = function(_) {
64779         if (!arguments.length) return state;
64780         state = _;
64781         entityEditor.state(state);
64782         return inspector;
64783     };
64784
64785
64786     inspector.entityID = function(_) {
64787         if (!arguments.length) return entityID;
64788         entityID = _;
64789         return inspector;
64790     };
64791
64792
64793     inspector.newFeature = function(_) {
64794         if (!arguments.length) return newFeature;
64795         newFeature = _;
64796         return inspector;
64797     };
64798
64799
64800     return inspector;
64801 }
64802
64803 function uiNotice(context) {
64804
64805     return function(selection) {
64806         var div = selection
64807             .append('div')
64808             .attr('class', 'notice');
64809
64810         var button = div
64811             .append('button')
64812             .attr('class', 'zoom-to notice')
64813             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
64814
64815         button
64816             .call(svgIcon('#icon-plus', 'pre-text'))
64817             .append('span')
64818             .attr('class', 'label')
64819             .text(t('zoom_in_edit'));
64820
64821
64822         function disableTooHigh() {
64823             div.style('display', context.editable() ? 'none' : 'block');
64824         }
64825
64826         context.map()
64827             .on('move.notice', lodash.debounce(disableTooHigh, 500));
64828
64829         disableTooHigh();
64830     };
64831 }
64832
64833 function uiSidebar(context) {
64834     var inspector = uiInspector(context),
64835         current;
64836
64837
64838     function sidebar(selection) {
64839         var featureListWrap = selection
64840             .append('div')
64841             .attr('class', 'feature-list-pane')
64842             .call(uiFeatureList(context));
64843
64844         selection
64845             .call(uiNotice(context));
64846
64847         var inspectorWrap = selection
64848             .append('div')
64849             .attr('class', 'inspector-hidden inspector-wrap fr');
64850
64851
64852         function hover(id) {
64853             if (!current && context.hasEntity(id)) {
64854                 featureListWrap
64855                     .classed('inspector-hidden', true);
64856
64857                 inspectorWrap
64858                     .classed('inspector-hidden', false)
64859                     .classed('inspector-hover', true);
64860
64861                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
64862                     inspector
64863                         .state('hover')
64864                         .entityID(id);
64865
64866                     inspectorWrap
64867                         .call(inspector);
64868                 }
64869
64870             } else if (!current) {
64871                 featureListWrap
64872                     .classed('inspector-hidden', false);
64873                 inspectorWrap
64874                     .classed('inspector-hidden', true);
64875                 inspector
64876                     .state('hide');
64877             }
64878         }
64879
64880
64881         sidebar.hover = lodash.throttle(hover, 200);
64882
64883
64884         sidebar.select = function(id, newFeature) {
64885             if (!current && id) {
64886                 featureListWrap
64887                     .classed('inspector-hidden', true);
64888
64889                 inspectorWrap
64890                     .classed('inspector-hidden', false)
64891                     .classed('inspector-hover', false);
64892
64893                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
64894                     inspector
64895                         .state('select')
64896                         .entityID(id)
64897                         .newFeature(newFeature);
64898
64899                     inspectorWrap
64900                         .call(inspector);
64901                 }
64902
64903             } else if (!current) {
64904                 featureListWrap
64905                     .classed('inspector-hidden', false);
64906                 inspectorWrap
64907                     .classed('inspector-hidden', true);
64908                 inspector
64909                     .state('hide');
64910             }
64911         };
64912
64913
64914         sidebar.show = function(component) {
64915             featureListWrap
64916                 .classed('inspector-hidden', true);
64917             inspectorWrap
64918                 .classed('inspector-hidden', true);
64919
64920             if (current) current.remove();
64921             current = selection
64922                 .append('div')
64923                 .attr('class', 'sidebar-component')
64924                 .call(component);
64925         };
64926
64927
64928         sidebar.hide = function() {
64929             featureListWrap
64930                 .classed('inspector-hidden', false);
64931             inspectorWrap
64932                 .classed('inspector-hidden', true);
64933
64934             if (current) current.remove();
64935             current = null;
64936         };
64937     }
64938
64939
64940     sidebar.hover = function() {};
64941     sidebar.hover.cancel = function() {};
64942     sidebar.select = function() {};
64943     sidebar.show = function() {};
64944     sidebar.hide = function() {};
64945
64946     return sidebar;
64947 }
64948
64949 function uiSpinner(context) {
64950     var connection = context.connection();
64951
64952
64953     return function(selection) {
64954         var img = selection
64955             .append('img')
64956             .attr('src', context.imagePath('loader-black.gif'))
64957             .style('opacity', 0);
64958
64959         connection
64960             .on('loading.spinner', function() {
64961                 img.transition()
64962                     .style('opacity', 1);
64963             });
64964
64965         connection
64966             .on('loaded.spinner', function() {
64967                 img.transition()
64968                     .style('opacity', 0);
64969             });
64970     };
64971 }
64972
64973 function uiSplash(context) {
64974
64975     return function(selection$$1) {
64976         if (context.storage('sawSplash'))
64977              return;
64978
64979         context.storage('sawSplash', true);
64980
64981         var modalSelection = uiModal(selection$$1);
64982
64983         modalSelection.select('.modal')
64984             .attr('class', 'modal-splash modal col6');
64985
64986         var introModal = modalSelection.select('.content')
64987             .append('div')
64988             .attr('class', 'fillL');
64989
64990         introModal
64991             .append('div')
64992             .attr('class','modal-section cf')
64993             .append('h3').text(t('splash.welcome'));
64994
64995         introModal
64996             .append('div')
64997             .attr('class','modal-section')
64998             .append('p')
64999             .html(t('splash.text', {
65000                 version: context.version,
65001                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
65002                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
65003             }));
65004
65005         var buttons = introModal
65006             .append('div')
65007             .attr('class', 'modal-actions cf');
65008
65009         buttons
65010             .append('button')
65011             .attr('class', 'col6 walkthrough')
65012             .text(t('splash.walkthrough'))
65013             .on('click', function() {
65014                 select(document.body).call(uiIntro(context));
65015                 modalSelection.close();
65016             });
65017
65018         buttons
65019             .append('button')
65020             .attr('class', 'col6 start')
65021             .text(t('splash.start'))
65022             .on('click', modalSelection.close);
65023
65024         modalSelection.select('button.close')
65025             .attr('class','hide');
65026
65027     };
65028 }
65029
65030 function uiStatus(context) {
65031     var connection = context.connection();
65032
65033     return function(selection$$1) {
65034
65035         function update() {
65036             connection.status(function(err, apiStatus) {
65037                 selection$$1.html('');
65038
65039                 if (err) {
65040                     if (apiStatus === 'rateLimited') {
65041                         selection$$1
65042                             .text(t('status.rateLimit'))
65043                             .append('a')
65044                             .attr('class', 'api-status-login')
65045                             .attr('target', '_blank')
65046                             .call(svgIcon('#icon-out-link', 'inline'))
65047                             .append('span')
65048                             .text(t('login'))
65049                             .on('click.login', function() {
65050                                 event.preventDefault();
65051                                 connection.authenticate();
65052                             });
65053                     } else {
65054                         // TODO: nice messages for different error types
65055                         selection$$1.text(t('status.error'));
65056                     }
65057
65058                 } else if (apiStatus === 'readonly') {
65059                     selection$$1.text(t('status.readonly'));
65060                 } else if (apiStatus === 'offline') {
65061                     selection$$1.text(t('status.offline'));
65062                 }
65063
65064                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
65065             });
65066         }
65067
65068         connection
65069             .on('change', function() { update(selection$$1); });
65070
65071         window.setInterval(update, 90000);
65072         update(selection$$1);
65073     };
65074 }
65075
65076 function uiUndoRedo(context) {
65077     var commands = [{
65078         id: 'undo',
65079         cmd: uiCmd('⌘Z'),
65080         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
65081         annotation: function() { return context.history().undoAnnotation(); }
65082     }, {
65083         id: 'redo',
65084         cmd: uiCmd('⌘⇧Z'),
65085         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
65086         annotation: function() { return context.history().redoAnnotation(); }
65087     }];
65088
65089
65090     function saving() {
65091         return context.mode().id === 'save';
65092     }
65093
65094
65095     return function(selection$$1) {
65096         var tooltipBehavior = tooltip()
65097             .placement('bottom')
65098             .html(true)
65099             .title(function (d) {
65100                 return uiTooltipHtml(d.annotation() ?
65101                     t(d.id + '.tooltip', {action: d.annotation()}) :
65102                     t(d.id + '.nothing'), d.cmd);
65103             });
65104
65105         var buttons = selection$$1.selectAll('button')
65106             .data(commands)
65107             .enter()
65108             .append('button')
65109             .attr('class', 'col6 disabled')
65110             .on('click', function(d) { return d.action(); })
65111             .call(tooltipBehavior);
65112
65113         buttons.each(function(d) {
65114             var iconName = d.id;
65115             if (textDirection === 'rtl') {
65116                 if (iconName === 'undo') {
65117                     iconName = 'redo';
65118                 } else if (iconName === 'redo') {
65119                     iconName = 'undo';
65120                 }
65121             }
65122             select(this)
65123                 .call(svgIcon('#icon-' + iconName));
65124         });
65125
65126         var keybinding = d3keybinding('undo')
65127             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
65128             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
65129
65130         select(document)
65131             .call(keybinding);
65132
65133         context.history()
65134             .on('change.undo_redo', update);
65135
65136         context
65137             .on('enter.undo_redo', update);
65138
65139         function update() {
65140             buttons
65141                 .property('disabled', saving())
65142                 .classed('disabled', function(d) { return !d.annotation(); })
65143                 .each(function() {
65144                     var selection$$1 = select(this);
65145                     if (selection$$1.property('tooltipVisible')) {
65146                         selection$$1.call(tooltipBehavior.show);
65147                     }
65148                 });
65149         }
65150     };
65151 }
65152
65153 function uiZoom(context) {
65154     var zooms = [{
65155         id: 'zoom-in',
65156         icon: 'plus',
65157         title: t('zoom.in'),
65158         action: context.zoomIn,
65159         key: '+'
65160     }, {
65161         id: 'zoom-out',
65162         icon: 'minus',
65163         title: t('zoom.out'),
65164         action: context.zoomOut,
65165         key: '-'
65166     }];
65167
65168
65169     function zoomIn() {
65170         event.preventDefault();
65171         if (!context.inIntro()) context.zoomIn();
65172     }
65173
65174
65175     function zoomOut() {
65176         event.preventDefault();
65177         if (!context.inIntro()) context.zoomOut();
65178     }
65179
65180
65181     function zoomInFurther() {
65182         event.preventDefault();
65183         if (!context.inIntro()) context.zoomInFurther();
65184     }
65185
65186
65187     function zoomOutFurther() {
65188         event.preventDefault();
65189         if (!context.inIntro()) context.zoomOutFurther();
65190     }
65191
65192
65193     return function(selection$$1) {
65194         var button = selection$$1.selectAll('button')
65195             .data(zooms)
65196             .enter()
65197             .append('button')
65198             .attr('tabindex', -1)
65199             .attr('class', function(d) { return d.id; })
65200             .on('click.editor', function(d) { d.action(); })
65201             .call(tooltip()
65202                 .placement((textDirection === 'rtl') ? 'right' : 'left')
65203                 .html(true)
65204                 .title(function(d) {
65205                     return uiTooltipHtml(d.title, d.key);
65206                 })
65207             );
65208
65209         button.each(function(d) {
65210             select(this)
65211                 .call(svgIcon('#icon-' + d.icon, 'light'));
65212         });
65213
65214         var keybinding = d3keybinding('zoom');
65215
65216         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
65217             keybinding.on([key, '⇧' + key], zoomIn);
65218             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
65219         });
65220         lodash.each(['-','ffminus','dash'], function(key) {
65221             keybinding.on([key, '⇧' + key], zoomOut);
65222             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
65223         });
65224
65225         select(document)
65226             .call(keybinding);
65227     };
65228 }
65229
65230 function uiInit(context) {
65231     var uiInitCounter = 0;
65232
65233
65234     function render(container) {
65235         container
65236             .attr('dir', textDirection);
65237
65238         var map$$1 = context.map();
65239
65240         var hash = behaviorHash(context);
65241         hash();
65242
65243         if (!hash.hadHash) {
65244             map$$1.centerZoom([0, 0], 2);
65245         }
65246
65247         container
65248             .append('svg')
65249             .attr('id', 'defs')
65250             .call(svgDefs(context));
65251
65252         container
65253             .append('div')
65254             .attr('id', 'sidebar')
65255             .attr('class', 'col4')
65256             .call(ui.sidebar);
65257
65258         var content = container
65259             .append('div')
65260             .attr('id', 'content')
65261             .attr('class', 'active');
65262
65263         var bar = content
65264             .append('div')
65265             .attr('id', 'bar')
65266             .attr('class', 'fillD');
65267
65268         content
65269             .append('div')
65270             .attr('id', 'map')
65271             .attr('dir', 'ltr')
65272             .call(map$$1);
65273
65274         content
65275             .call(uiMapInMap(context));
65276
65277         content
65278             .append('div')
65279             .call(uiInfo(context));
65280
65281         bar
65282             .append('div')
65283             .attr('class', 'spacer col4');
65284
65285         var limiter = bar.append('div')
65286             .attr('class', 'limiter');
65287
65288         limiter
65289             .append('div')
65290             .attr('class', 'button-wrap joined col3')
65291             .call(uiModes(context), limiter);
65292
65293         limiter
65294             .append('div')
65295             .attr('class', 'button-wrap joined col1')
65296             .call(uiUndoRedo(context));
65297
65298         limiter
65299             .append('div')
65300             .attr('class', 'button-wrap col1')
65301             .call(uiSave(context));
65302
65303         bar
65304             .append('div')
65305             .attr('class', 'full-screen')
65306             .call(uiFullScreen(context));
65307
65308         bar
65309             .append('div')
65310             .attr('class', 'spinner')
65311             .call(uiSpinner(context));
65312
65313         var controls = bar
65314             .append('div')
65315             .attr('class', 'map-controls');
65316
65317         controls
65318             .append('div')
65319             .attr('class', 'map-control zoombuttons')
65320             .call(uiZoom(context));
65321
65322         controls
65323             .append('div')
65324             .attr('class', 'map-control geolocate-control')
65325             .call(uiGeolocate(context));
65326
65327         controls
65328             .append('div')
65329             .attr('class', 'map-control background-control')
65330             .call(uiBackground(context));
65331
65332         controls
65333             .append('div')
65334             .attr('class', 'map-control map-data-control')
65335             .call(uiMapData(context));
65336
65337         controls
65338             .append('div')
65339             .attr('class', 'map-control help-control')
65340             .call(uiHelp(context));
65341
65342         var about = content
65343             .append('div')
65344             .attr('id', 'about');
65345
65346         about
65347             .append('div')
65348             .attr('id', 'attrib')
65349             .attr('dir', 'ltr')
65350             .call(uiAttribution(context));
65351
65352         var footer = about
65353             .append('div')
65354             .attr('id', 'footer')
65355             .attr('class', 'fillD');
65356
65357         footer
65358             .append('div')
65359             .attr('class', 'api-status')
65360             .call(uiStatus(context));
65361
65362         footer
65363             .append('div')
65364             .attr('id', 'scale-block')
65365             .call(uiScale(context));
65366
65367         var aboutList = footer
65368             .append('div')
65369             .attr('id', 'info-block')
65370             .append('ul')
65371             .attr('id', 'about-list');
65372
65373         if (!context.embed()) {
65374             aboutList.call(uiAccount(context));
65375         }
65376
65377         aboutList
65378             .append('li')
65379             .append('a')
65380             .attr('target', '_blank')
65381             .attr('tabindex', -1)
65382             .attr('href', 'https://github.com/openstreetmap/iD')
65383             .text(context.version);
65384
65385         var issueLinks = aboutList
65386             .append('li');
65387
65388         issueLinks
65389             .append('a')
65390             .attr('target', '_blank')
65391             .attr('tabindex', -1)
65392             .attr('href', 'https://github.com/openstreetmap/iD/issues')
65393             .call(svgIcon('#icon-bug', 'light'))
65394             .call(tooltip().title(t('report_a_bug')).placement('top'));
65395
65396         issueLinks
65397             .append('a')
65398             .attr('target', '_blank')
65399             .attr('tabindex', -1)
65400             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
65401             .call(svgIcon('#icon-translate', 'light'))
65402             .call(tooltip().title(t('help_translate')).placement('top'));
65403
65404         aboutList
65405             .append('li')
65406             .attr('class', 'feature-warning')
65407             .attr('tabindex', -1)
65408             .call(uiFeatureInfo(context));
65409
65410         aboutList
65411             .append('li')
65412             .attr('class', 'user-list')
65413             .attr('tabindex', -1)
65414             .call(uiContributors(context));
65415
65416
65417         window.onbeforeunload = function() {
65418             return context.save();
65419         };
65420
65421         window.onunload = function() {
65422             context.history().unlock();
65423         };
65424
65425         var mapDimensions = map$$1.dimensions();
65426
65427
65428         function onResize() {
65429             mapDimensions = utilGetDimensions(content, true);
65430             map$$1.dimensions(mapDimensions);
65431         }
65432
65433         select(window)
65434             .on('resize.editor', onResize);
65435
65436         onResize();
65437
65438         function pan(d) {
65439             return function() {
65440                 event.preventDefault();
65441                 if (!context.inIntro()) {
65442                     context.pan(d, 100);
65443                 }
65444             };
65445         }
65446
65447
65448         // pan amount
65449         var pa = 10;
65450
65451         var keybinding = d3keybinding('main')
65452             .on('⌫', function() { event.preventDefault(); })
65453             .on('←', pan([pa, 0]))
65454             .on('↑', pan([0, pa]))
65455             .on('→', pan([-pa, 0]))
65456             .on('↓', pan([0, -pa]))
65457             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
65458             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
65459             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
65460             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
65461
65462         select(document)
65463             .call(keybinding);
65464
65465         context.enter(modeBrowse(context));
65466
65467         if (!uiInitCounter++) {
65468             context.container()
65469                 .call(uiSplash(context))
65470                 .call(uiRestore(context));
65471         }
65472
65473         var authenticating = uiLoading(context)
65474             .message(t('loading_auth'))
65475             .blocking(true);
65476
65477         context.connection()
65478             .on('authLoading.ui', function() {
65479                 context.container()
65480                     .call(authenticating);
65481             })
65482             .on('authDone.ui', function() {
65483                 authenticating.close();
65484             });
65485
65486         uiInitCounter++;
65487     }
65488
65489
65490     var renderCallback;
65491
65492     function ui(node, callback) {
65493         renderCallback = callback;
65494         var container = select(node);
65495         context.container(container);
65496         context.loadLocale(function(err) {
65497             if (!err) {
65498                 render(container);
65499             }
65500             if (callback) {
65501                 callback(err);
65502             }
65503         });
65504     }
65505
65506
65507     ui.restart = function(arg) {
65508         context.locale(arg);
65509         context.loadLocale(function(err) {
65510             if (!err) {
65511                 context.container().selectAll('*').remove();
65512                 render(context.container());
65513                 if (renderCallback) renderCallback();
65514             }
65515         });
65516     };
65517
65518
65519     ui.sidebar = uiSidebar(context);
65520
65521     return ui;
65522 }
65523
65524 function uiCommit(context) {
65525     var dispatch$$1 = dispatch('cancel', 'save');
65526
65527
65528     function commit(selection$$1) {
65529         var changes = context.history().changes(),
65530             summary = context.history().difference().summary();
65531
65532         selection$$1
65533             .append('div')
65534             .attr('class', 'header fillL')
65535             .append('h3')
65536             .text(t('commit.title'));
65537
65538         var body = selection$$1
65539             .append('div')
65540             .attr('class', 'body');
65541
65542         var commentSection = body
65543             .append('div')
65544             .attr('class', 'modal-section form-field commit-form');
65545
65546         commentSection
65547             .append('label')
65548             .attr('class', 'form-label')
65549             .text(t('commit.message_label'));
65550
65551         var commentField = commentSection
65552             .append('textarea')
65553             .attr('placeholder', t('commit.description_placeholder'))
65554             .attr('maxlength', 255)
65555             .property('value', context.storage('comment') || '')
65556             .on('input.save', checkComment)
65557             .on('change.save', checkComment)
65558             .on('blur.save', function() {
65559                 context.storage('comment', this.value);
65560             });
65561
65562
65563         commentField.node().select();
65564
65565         context.connection().userChangesets(function (err, changesets) {
65566             if (err) return;
65567
65568             var comments = changesets.map(function(changeset) {
65569                 return {
65570                     title: changeset.tags.comment,
65571                     value: changeset.tags.comment
65572                 };
65573             });
65574
65575             commentField
65576                 .call(d3combobox()
65577                     .caseSensitive(true)
65578                     .data(lodash.uniqBy(comments, 'title'))
65579                 );
65580         });
65581
65582         var clippyArea = commentSection.append('div')
65583             .attr('class', 'clippy-area');
65584
65585         var changeSetInfo = commentSection.append('div')
65586             .attr('class', 'changeset-info');
65587
65588         changeSetInfo.append('a')
65589             .attr('target', '_blank')
65590             .attr('tabindex', -1)
65591             .call(svgIcon('#icon-out-link', 'inline'))
65592             .attr('href', t('commit.about_changeset_comments_link'))
65593             .append('span')
65594             .text(t('commit.about_changeset_comments'));
65595
65596
65597         // Warnings
65598         var warnings = body.selectAll('div.warning-section')
65599             .data([context.history().validate(changes)]);
65600
65601         warnings = warnings.enter()
65602             .append('div')
65603             .attr('class', 'modal-section warning-section fillL2')
65604             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
65605             .style('background', '#ffb')
65606             .merge(warnings);
65607
65608         warnings
65609             .append('h3')
65610             .text(t('commit.warnings'));
65611
65612         warnings
65613             .append('ul')
65614             .attr('class', 'changeset-list');
65615
65616         var warningLi = warnings.select('ul').selectAll('li')
65617             .data(function(d) { return d; });
65618
65619         warningLi = warningLi.enter()
65620             .append('li')
65621             .on('mouseover', mouseover)
65622             .on('mouseout', mouseout)
65623             .on('click', warningClick)
65624             .merge(warningLi);
65625
65626         warningLi
65627             .call(svgIcon('#icon-alert', 'pre-text'));
65628
65629         warningLi
65630             .append('strong')
65631             .text(function(d) { return d.message; });
65632
65633         warningLi.filter(function(d) { return d.tooltip; })
65634             .call(tooltip()
65635                 .title(function(d) { return d.tooltip; })
65636                 .placement('top')
65637             );
65638
65639
65640         // Upload Explanation
65641         var saveSection = body
65642             .append('div')
65643             .attr('class','modal-section save-section fillL cf');
65644
65645         var prose = saveSection
65646             .append('p')
65647             .attr('class', 'commit-info')
65648             .html(t('commit.upload_explanation'));
65649
65650
65651         context.connection().userDetails(function(err, user) {
65652             if (err) return;
65653
65654             var userLink = select(document.createElement('div'));
65655
65656             if (user.image_url) {
65657                 userLink
65658                     .append('img')
65659                     .attr('src', user.image_url)
65660                     .attr('class', 'icon pre-text user-icon');
65661             }
65662
65663             userLink
65664                 .append('a')
65665                 .attr('class','user-info')
65666                 .text(user.display_name)
65667                 .attr('href', context.connection().userURL(user.display_name))
65668                 .attr('tabindex', -1)
65669                 .attr('target', '_blank');
65670
65671             prose
65672                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
65673         });
65674
65675
65676         // Buttons
65677         var buttonSection = saveSection
65678             .append('div')
65679             .attr('class','buttons fillL cf');
65680
65681         var cancelButton = buttonSection
65682             .append('button')
65683             .attr('class', 'secondary-action col5 button cancel-button')
65684             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65685
65686         cancelButton
65687             .append('span')
65688             .attr('class', 'label')
65689             .text(t('commit.cancel'));
65690
65691         var saveButton = buttonSection
65692             .append('button')
65693             .attr('class', 'action col5 button save-button')
65694             .attr('disabled', function() {
65695                 var n = select('.commit-form textarea').node();
65696                 return (n && n.value.length) ? null : true;
65697             })
65698             .on('click.save', function() {
65699                 dispatch$$1.call('save', this, {
65700                     comment: commentField.node().value
65701                 });
65702             });
65703
65704         saveButton
65705             .append('span')
65706             .attr('class', 'label')
65707             .text(t('commit.save'));
65708
65709
65710         // Changes
65711         var changeSection = body
65712             .append('div')
65713             .attr('class', 'commit-section modal-section fillL2');
65714
65715         changeSection.append('h3')
65716             .text(t('commit.changes', { count: summary.length }));
65717
65718         var li = changeSection
65719             .append('ul')
65720             .attr('class', 'changeset-list')
65721             .selectAll('li')
65722             .data(summary);
65723
65724         li = li.enter()
65725             .append('li')
65726             .on('mouseover', mouseover)
65727             .on('mouseout', mouseout)
65728             .on('click', zoomToEntity)
65729             .merge(li);
65730
65731         li.each(function(d) {
65732             select(this)
65733                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
65734         });
65735
65736         li.append('span')
65737             .attr('class', 'change-type')
65738             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
65739
65740         li.append('strong')
65741             .attr('class', 'entity-type')
65742             .text(function(d) {
65743                 var matched = context.presets().match(d.entity, d.graph);
65744                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
65745             });
65746
65747         li.append('span')
65748             .attr('class', 'entity-name')
65749             .text(function(d) {
65750                 var name = utilDisplayName(d.entity) || '',
65751                     string = '';
65752                 if (name !== '') string += ':';
65753                 return string += ' ' + name;
65754             });
65755
65756         li.style('opacity', 0)
65757             .transition()
65758             .style('opacity', 1);
65759
65760
65761         // Call checkComment off the bat, in case a changeset
65762         // comment is recovered from localStorage
65763         utilTriggerEvent(commentField, 'input');
65764
65765
65766         function mouseover(d) {
65767             if (d.entity) {
65768                 context.surface().selectAll(
65769                     utilEntityOrMemberSelector([d.entity.id], context.graph())
65770                 ).classed('hover', true);
65771             }
65772         }
65773
65774
65775         function mouseout() {
65776             context.surface().selectAll('.hover')
65777                 .classed('hover', false);
65778         }
65779
65780
65781         function warningClick(d) {
65782             if (d.entity) {
65783                 context.map().zoomTo(d.entity);
65784                 context.enter(
65785                     modeSelect(context, [d.entity.id]).suppressMenu(true)
65786                 );
65787             }
65788         }
65789
65790
65791         function zoomToEntity(change) {
65792             var entity = change.entity;
65793             if (change.changeType !== 'deleted' &&
65794                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
65795                 context.map().zoomTo(entity);
65796                 context.surface().selectAll(
65797                     utilEntityOrMemberSelector([entity.id], context.graph()))
65798                     .classed('hover', true);
65799             }
65800         }
65801
65802
65803         function checkComment() {
65804             selectAll('.save-section .save-button')
65805                 .attr('disabled', (this.value.length ? null : true));
65806
65807             var googleWarning = clippyArea
65808                .html('')
65809                .selectAll('a')
65810                .data(this.value.match(/google/i) ? [true] : []);
65811
65812             googleWarning.exit()
65813                 .remove();
65814
65815             googleWarning.enter()
65816                .append('a')
65817                .attr('target', '_blank')
65818                .attr('tabindex', -1)
65819                .call(svgIcon('#icon-alert', 'inline'))
65820                .attr('href', t('commit.google_warning_link'))
65821                .append('span')
65822                .text(t('commit.google_warning'));
65823         }
65824     }
65825
65826     return utilRebind(commit, dispatch$$1, 'on');
65827 }
65828
65829 function uiConfirm(selection) {
65830     var modalSelection = uiModal(selection);
65831
65832     modalSelection.select('.modal')
65833         .classed('modal-alert', true);
65834
65835     var section = modalSelection.select('.content');
65836
65837     section.append('div')
65838         .attr('class', 'modal-section header');
65839
65840     section.append('div')
65841         .attr('class', 'modal-section message-text');
65842
65843     var buttons = section.append('div')
65844         .attr('class', 'modal-section buttons cf');
65845
65846
65847     modalSelection.okButton = function() {
65848         buttons
65849             .append('button')
65850             .attr('class', 'action col4')
65851             .on('click.confirm', function() {
65852                 modalSelection.remove();
65853             })
65854             .text(t('confirm.okay'));
65855
65856         return modalSelection;
65857     };
65858
65859
65860     return modalSelection;
65861 }
65862
65863 function uiConflicts(context) {
65864     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
65865         list;
65866
65867
65868     function conflicts(selection$$1) {
65869         var header = selection$$1
65870             .append('div')
65871             .attr('class', 'header fillL');
65872
65873         header
65874             .append('button')
65875             .attr('class', 'fr')
65876             .on('click', function() { dispatch$$1.call('cancel'); })
65877             .call(svgIcon('#icon-close'));
65878
65879         header
65880             .append('h3')
65881             .text(t('save.conflict.header'));
65882
65883         var body = selection$$1
65884             .append('div')
65885             .attr('class', 'body fillL');
65886
65887         body
65888             .append('div')
65889             .attr('class', 'conflicts-help')
65890             .text(t('save.conflict.help'))
65891             .append('a')
65892             .attr('class', 'conflicts-download')
65893             .text(t('save.conflict.download_changes'))
65894             .on('click.download', function() { dispatch$$1.call('download'); });
65895
65896         body
65897             .append('div')
65898             .attr('class', 'conflict-container fillL3')
65899             .call(showConflict, 0);
65900
65901         body
65902             .append('div')
65903             .attr('class', 'conflicts-done')
65904             .attr('opacity', 0)
65905             .style('display', 'none')
65906             .text(t('save.conflict.done'));
65907
65908         var buttons = body
65909             .append('div')
65910             .attr('class','buttons col12 joined conflicts-buttons');
65911
65912         buttons
65913             .append('button')
65914             .attr('disabled', list.length > 1)
65915             .attr('class', 'action conflicts-button col6')
65916             .text(t('save.title'))
65917             .on('click.try_again', function() { dispatch$$1.call('save'); });
65918
65919         buttons
65920             .append('button')
65921             .attr('class', 'secondary-action conflicts-button col6')
65922             .text(t('confirm.cancel'))
65923             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65924     }
65925
65926
65927     function showConflict(selection$$1, index) {
65928         if (index < 0 || index >= list.length) return;
65929
65930         var parent = select(selection$$1.node().parentNode);
65931
65932         // enable save button if this is the last conflict being reviewed..
65933         if (index === list.length - 1) {
65934             window.setTimeout(function() {
65935                 parent.select('.conflicts-button')
65936                     .attr('disabled', null);
65937
65938                 parent.select('.conflicts-done')
65939                     .transition()
65940                     .attr('opacity', 1)
65941                     .style('display', 'block');
65942             }, 250);
65943         }
65944
65945         var item = selection$$1
65946             .selectAll('.conflict')
65947             .data([list[index]]);
65948
65949         var enter = item.enter()
65950             .append('div')
65951             .attr('class', 'conflict');
65952
65953         enter
65954             .append('h4')
65955             .attr('class', 'conflict-count')
65956             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
65957
65958         enter
65959             .append('a')
65960             .attr('class', 'conflict-description')
65961             .attr('href', '#')
65962             .text(function(d) { return d.name; })
65963             .on('click', function(d) {
65964                 zoomToEntity(d.id);
65965                 event.preventDefault();
65966             });
65967
65968         var details = enter
65969             .append('div')
65970             .attr('class', 'conflict-detail-container');
65971
65972         details
65973             .append('ul')
65974             .attr('class', 'conflict-detail-list')
65975             .selectAll('li')
65976             .data(function(d) { return d.details || []; })
65977             .enter()
65978             .append('li')
65979             .attr('class', 'conflict-detail-item')
65980             .html(function(d) { return d; });
65981
65982         details
65983             .append('div')
65984             .attr('class', 'conflict-choices')
65985             .call(addChoices);
65986
65987         details
65988             .append('div')
65989             .attr('class', 'conflict-nav-buttons joined cf')
65990             .selectAll('button')
65991             .data(['previous', 'next'])
65992             .enter()
65993             .append('button')
65994             .text(function(d) { return t('save.conflict.' + d); })
65995             .attr('class', 'conflict-nav-button action col6')
65996             .attr('disabled', function(d, i) {
65997                 return (i === 0 && index === 0) ||
65998                     (i === 1 && index === list.length - 1) || null;
65999             })
66000             .on('click', function(d, i) {
66001                 var container = parent.select('.conflict-container'),
66002                 sign = (i === 0 ? -1 : 1);
66003
66004                 container
66005                     .selectAll('.conflict')
66006                     .remove();
66007
66008                 container
66009                     .call(showConflict, index + sign);
66010
66011                 event.preventDefault();
66012             });
66013
66014         item.exit()
66015             .remove();
66016     }
66017
66018
66019     function addChoices(selection$$1) {
66020         var choices = selection$$1
66021             .append('ul')
66022             .attr('class', 'layer-list')
66023             .selectAll('li')
66024             .data(function(d) { return d.choices || []; });
66025
66026         var enter = choices.enter()
66027             .append('li')
66028             .attr('class', 'layer');
66029
66030         var label = enter
66031             .append('label');
66032
66033         label
66034             .append('input')
66035             .attr('type', 'radio')
66036             .attr('name', function(d) { return d.id; })
66037             .on('change', function(d, i) {
66038                 var ul = this.parentNode.parentNode.parentNode;
66039                 ul.__data__.chosen = i;
66040                 choose(ul, d);
66041             });
66042
66043         label
66044             .append('span')
66045             .text(function(d) { return d.text; });
66046
66047         choices
66048             .each(function(d, i) {
66049                 var ul = this.parentNode;
66050                 if (ul.__data__.chosen === i) choose(ul, d);
66051             });
66052     }
66053
66054
66055     function choose(ul, datum) {
66056         if (event) event.preventDefault();
66057
66058         select(ul)
66059             .selectAll('li')
66060             .classed('active', function(d) { return d === datum; })
66061             .selectAll('input')
66062             .property('checked', function(d) { return d === datum; });
66063
66064         var extent$$1 = geoExtent$$1(),
66065             entity;
66066
66067         entity = context.graph().hasEntity(datum.id);
66068         if (entity) extent$$1._extend(entity.extent(context.graph()));
66069
66070         datum.action();
66071
66072         entity = context.graph().hasEntity(datum.id);
66073         if (entity) extent$$1._extend(entity.extent(context.graph()));
66074
66075         zoomToEntity(datum.id, extent$$1);
66076     }
66077
66078
66079     function zoomToEntity(id, extent$$1) {
66080         context.surface().selectAll('.hover')
66081             .classed('hover', false);
66082
66083         var entity = context.graph().hasEntity(id);
66084         if (entity) {
66085             if (extent$$1) {
66086                 context.map().trimmedExtent(extent$$1);
66087             } else {
66088                 context.map().zoomTo(entity);
66089             }
66090             context.surface().selectAll(
66091                 utilEntityOrMemberSelector([entity.id], context.graph()))
66092                 .classed('hover', true);
66093         }
66094     }
66095
66096
66097     // The conflict list should be an array of objects like:
66098     // {
66099     //     id: id,
66100     //     name: entityName(local),
66101     //     details: merge.conflicts(),
66102     //     chosen: 1,
66103     //     choices: [
66104     //         choice(id, keepMine, forceLocal),
66105     //         choice(id, keepTheirs, forceRemote)
66106     //     ]
66107     // }
66108     conflicts.list = function(_) {
66109         if (!arguments.length) return list;
66110         list = _;
66111         return conflicts;
66112     };
66113
66114
66115     return utilRebind(conflicts, dispatch$$1, 'on');
66116 }
66117
66118 function uiFlash(selection) {
66119     var modalSelection = uiModal(selection);
66120
66121     modalSelection.select('.modal')
66122         .classed('modal-flash', true);
66123
66124     modalSelection.select('.content')
66125         .classed('modal-section', true)
66126         .append('div')
66127         .attr('class', 'description');
66128
66129     modalSelection.on('click.flash', function() {
66130         modalSelection.remove();
66131     });
66132
66133     setTimeout(function() {
66134         modalSelection.remove();
66135         return true;
66136     }, 1500);
66137
66138
66139     return modalSelection;
66140 }
66141
66142 function uiLasso(context) {
66143     var group, polygon;
66144
66145     lasso.coordinates = [];
66146
66147     function lasso(selection$$1) {
66148         context.container()
66149             .classed('lasso', true);
66150
66151         group = selection$$1
66152             .append('g')
66153             .attr('class', 'lasso hide');
66154
66155         polygon = group
66156             .append('path')
66157             .attr('class', 'lasso-path');
66158
66159         group
66160             .call(uiToggle(true));
66161     }
66162
66163
66164     function draw() {
66165         if (polygon) {
66166             polygon.data([lasso.coordinates])
66167                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
66168         }
66169     }
66170
66171
66172     lasso.extent = function () {
66173         return lasso.coordinates.reduce(function(extent$$1, point) {
66174             return extent$$1.extend(geoExtent$$1(point));
66175         }, geoExtent$$1());
66176     };
66177
66178
66179     lasso.p = function(_) {
66180         if (!arguments.length) return lasso;
66181         lasso.coordinates.push(_);
66182         draw();
66183         return lasso;
66184     };
66185
66186
66187     lasso.close = function() {
66188         if (group) {
66189             group.call(uiToggle(false, function() {
66190                 select(this).remove();
66191             }));
66192         }
66193         context.container().classed('lasso', false);
66194     };
66195
66196
66197     return lasso;
66198 }
66199
66200 function uiRadialMenu(context, operations) {
66201     var menu,
66202         center = [0, 0],
66203         tooltip;
66204
66205
66206     var radialMenu = function(selection$$1) {
66207         if (!operations.length) return;
66208
66209         selection$$1.node().parentNode.focus();
66210
66211         function click(operation) {
66212             event.stopPropagation();
66213             if (operation.disabled()) return;
66214             operation();
66215             radialMenu.close();
66216         }
66217
66218         menu = selection$$1
66219             .append('g')
66220             .attr('class', 'radial-menu')
66221             .attr('transform', 'translate(' + center + ')')
66222             .attr('opacity', 0);
66223
66224         menu
66225             .transition()
66226             .attr('opacity', 1);
66227
66228         var r = 50,
66229             a = Math.PI / 4,
66230             a0 = -Math.PI / 4,
66231             a1 = a0 + (operations.length - 1) * a;
66232
66233         menu
66234             .append('path')
66235             .attr('class', 'radial-menu-background')
66236             .attr('d', 'M' + r * Math.sin(a0) + ',' +
66237                              r * Math.cos(a0) +
66238                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
66239                              (r * Math.sin(a1) + 1e-3) + ',' +
66240                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
66241             .attr('stroke-width', 50)
66242             .attr('stroke-linecap', 'round');
66243
66244         var button = menu.selectAll()
66245             .data(operations)
66246             .enter()
66247             .append('g')
66248             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
66249             .classed('disabled', function(d) { return d.disabled(); })
66250             .attr('transform', function(d, i) {
66251                 return 'translate(' + geoRoundCoords([
66252                         r * Math.sin(a0 + i * a),
66253                         r * Math.cos(a0 + i * a)]).join(',') + ')';
66254             });
66255
66256         button
66257             .append('circle')
66258             .attr('r', 15)
66259             .on('click', click)
66260             .on('mousedown', mousedown)
66261             .on('mouseover', mouseover)
66262             .on('mouseout', mouseout);
66263
66264         button
66265             .append('use')
66266             .attr('transform', 'translate(-10,-10)')
66267             .attr('width', '20')
66268             .attr('height', '20')
66269             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
66270
66271         tooltip = select(document.body)
66272             .append('div')
66273             .attr('class', 'tooltip-inner radial-menu-tooltip');
66274
66275         function mousedown() {
66276             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
66277         }
66278
66279         function mouseover(d, i) {
66280             var rect = context.surfaceRect(),
66281                 angle = a0 + i * a,
66282                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
66283                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
66284                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
66285                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
66286
66287             tooltip
66288                 .style('top', null)
66289                 .style('left', null)
66290                 .style('bottom', null)
66291                 .style('right', null)
66292                 .style('display', 'block')
66293                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
66294
66295             if (i === 0) {
66296                 tooltip
66297                     .style('right', right)
66298                     .style('top', top);
66299             } else if (i >= 4) {
66300                 tooltip
66301                     .style('left', left)
66302                     .style('bottom', bottom);
66303             } else {
66304                 tooltip
66305                     .style('left', left)
66306                     .style('top', top);
66307             }
66308         }
66309
66310         function mouseout() {
66311             tooltip.style('display', 'none');
66312         }
66313     };
66314
66315
66316     radialMenu.close = function() {
66317         if (menu) {
66318             menu
66319                 .style('pointer-events', 'none')
66320                 .transition()
66321                 .attr('opacity', 0)
66322                 .remove();
66323         }
66324
66325         if (tooltip) {
66326             tooltip.remove();
66327         }
66328     };
66329
66330
66331     radialMenu.center = function(_) {
66332         if (!arguments.length) return center;
66333         center = _;
66334         return radialMenu;
66335     };
66336
66337
66338     return radialMenu;
66339 }
66340
66341 function uiSelectionList(context, selectedIDs) {
66342
66343     function selectEntity(entity) {
66344         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
66345     }
66346
66347
66348     function deselectEntity(entity) {
66349         event.stopPropagation();
66350         var index = selectedIDs.indexOf(entity.id);
66351         if (index > -1) {
66352             selectedIDs.splice(index, 1);
66353         }
66354         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
66355     }
66356
66357
66358     function selectionList(selection$$1) {
66359         selection$$1.classed('selection-list-pane', true);
66360
66361         var header = selection$$1
66362             .append('div')
66363             .attr('class', 'header fillL cf');
66364
66365         header
66366             .append('h3')
66367             .text(t('inspector.multiselect'));
66368
66369         var listWrap = selection$$1
66370             .append('div')
66371             .attr('class', 'inspector-body');
66372
66373         var list = listWrap
66374             .append('div')
66375             .attr('class', 'feature-list cf');
66376
66377         context.history().on('change.selection-list', drawList);
66378         drawList();
66379
66380
66381         function drawList() {
66382             var entities = selectedIDs
66383                 .map(function(id) { return context.hasEntity(id); })
66384                 .filter(function(entity) { return entity; });
66385
66386             var items = list.selectAll('.feature-list-item')
66387                 .data(entities, osmEntity$$1.key);
66388
66389             items.exit()
66390                 .remove();
66391
66392             // Enter
66393             var enter = items.enter()
66394                 .append('div')
66395                 .attr('class', 'feature-list-item')
66396                 .on('click', selectEntity);
66397
66398             var label = enter
66399                 .append('button')
66400                 .attr('class', 'label');
66401
66402             enter
66403                 .append('button')
66404                 .attr('class', 'close')
66405                 .on('click', deselectEntity)
66406                 .call(svgIcon('#icon-close'));
66407
66408             label
66409                 .append('span')
66410                 .attr('class', 'entity-geom-icon')
66411                 .call(svgIcon('', 'pre-text'));
66412
66413             label
66414                 .append('span')
66415                 .attr('class', 'entity-type');
66416
66417             label
66418                 .append('span')
66419                 .attr('class', 'entity-name');
66420
66421             // Update
66422             items = items.merge(enter);
66423
66424             items.selectAll('.entity-geom-icon use')
66425                 .attr('href', function() {
66426                     var entity = this.parentNode.parentNode.__data__;
66427                     return '#icon-' + context.geometry(entity.id);
66428                 });
66429
66430             items.selectAll('.entity-type')
66431                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
66432
66433             items.selectAll('.entity-name')
66434                 .text(function(entity) { return utilDisplayName(entity); });
66435         }
66436     }
66437
66438     return selectionList;
66439 }
66440
66441 function uiSourceSwitch(context) {
66442     var keys$$1;
66443
66444
66445     function click() {
66446         event.preventDefault();
66447
66448         if (context.history().hasChanges() &&
66449             !window.confirm(t('source_switch.lose_changes'))) return;
66450
66451         var live = select(this)
66452             .classed('live');
66453
66454         context.connection()
66455             .switch(live ? keys$$1[1] : keys$$1[0]);
66456
66457         context.enter(modeBrowse(context));
66458         context.flush();
66459
66460         select(this)
66461             .text(live ? t('source_switch.dev') : t('source_switch.live'))
66462             .classed('live', !live);
66463     }
66464
66465     var sourceSwitch = function(selection$$1) {
66466         selection$$1
66467             .append('a')
66468             .attr('href', '#')
66469             .text(t('source_switch.live'))
66470             .classed('live', true)
66471             .attr('tabindex', -1)
66472             .on('click', click);
66473     };
66474
66475
66476     sourceSwitch.keys = function(_) {
66477         if (!arguments.length) return keys$$1;
66478         keys$$1 = _;
66479         return sourceSwitch;
66480     };
66481
66482
66483     return sourceSwitch;
66484 }
66485
66486 function uiSuccess(context) {
66487     var dispatch$$1 = dispatch('cancel'),
66488         changeset;
66489
66490
66491     function success(selection$$1) {
66492         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
66493             ' ' + context.connection().changesetURL(changeset.id);
66494
66495         var header = selection$$1
66496             .append('div')
66497             .attr('class', 'header fillL');
66498
66499         header
66500             .append('button')
66501             .attr('class', 'fr')
66502             .on('click', function() { dispatch$$1.call('cancel'); })
66503             .call(svgIcon('#icon-close'));
66504
66505         header
66506             .append('h3')
66507             .text(t('success.just_edited'));
66508
66509         var body = selection$$1
66510             .append('div')
66511             .attr('class', 'body save-success fillL');
66512
66513         body
66514             .append('p')
66515             .html(t('success.help_html'));
66516
66517         body
66518             .append('a')
66519             .attr('class', 'details')
66520             .attr('target', '_blank')
66521             .attr('tabindex', -1)
66522             .call(svgIcon('#icon-out-link', 'inline'))
66523             .attr('href', t('success.help_link_url'))
66524             .append('span')
66525             .text(t('success.help_link_text'));
66526
66527         var changesetURL = context.connection().changesetURL(changeset.id);
66528
66529         body
66530             .append('a')
66531             .attr('class', 'button col12 osm')
66532             .attr('target', '_blank')
66533             .attr('href', changesetURL)
66534             .text(t('success.view_on_osm'));
66535
66536         var sharing = {
66537             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
66538             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
66539             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
66540         };
66541
66542         body.selectAll('.button.social')
66543             .data(entries(sharing))
66544             .enter()
66545             .append('a')
66546             .attr('class', 'button social col4')
66547             .attr('target', '_blank')
66548             .attr('href', function(d) { return d.value; })
66549             .call(tooltip()
66550                 .title(function(d) { return t('success.' + d.key); })
66551                 .placement('bottom'))
66552             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
66553     }
66554
66555
66556     success.changeset = function(_) {
66557         if (!arguments.length) return changeset;
66558         changeset = _;
66559         return success;
66560     };
66561
66562
66563     return utilRebind(success, dispatch$$1, 'on');
66564 }
66565
66566 function coreHistory(context) {
66567     var imageryUsed = ['Bing'],
66568         dispatch$$1 = dispatch('change', 'undone', 'redone'),
66569         lock = utilSessionMutex('lock'),
66570         duration = 150,
66571         stack$$1, index, tree$$1;
66572
66573
66574     // internal _act, accepts list of actions and eased time
66575     function _act(actions, t) {
66576         actions = Array.prototype.slice.call(actions);
66577
66578         var annotation;
66579
66580         if (!lodash.isFunction(lodash.last(actions))) {
66581             annotation = actions.pop();
66582         }
66583
66584         stack$$1[index].transform = context.projection.transform();
66585         stack$$1[index].selectedIDs = context.selectedIDs();
66586
66587         var graph = stack$$1[index].graph;
66588         for (var i = 0; i < actions.length; i++) {
66589             graph = actions[i](graph, t);
66590         }
66591
66592         return {
66593             graph: graph,
66594             annotation: annotation,
66595             imageryUsed: imageryUsed
66596         };
66597     }
66598
66599
66600     // internal _perform with eased time
66601     function _perform(args, t) {
66602         var previous = stack$$1[index].graph;
66603         stack$$1 = stack$$1.slice(0, index + 1);
66604         stack$$1.push(_act(args, t));
66605         index++;
66606         return change(previous);
66607     }
66608
66609
66610     // internal _replace with eased time
66611     function _replace(args, t) {
66612         var previous = stack$$1[index].graph;
66613         // assert(index == stack.length - 1)
66614         stack$$1[index] = _act(args, t);
66615         return change(previous);
66616     }
66617
66618
66619     // internal _overwrite with eased time
66620     function _overwrite(args, t) {
66621         var previous = stack$$1[index].graph;
66622         if (index > 0) {
66623             index--;
66624             stack$$1.pop();
66625         }
66626         stack$$1 = stack$$1.slice(0, index + 1);
66627         stack$$1.push(_act(args, t));
66628         index++;
66629         return change(previous);
66630     }
66631
66632
66633     // determine diffrence and dispatch a change event
66634     function change(previous) {
66635         var difference = coreDifference(previous, history.graph());
66636         dispatch$$1.call('change', this, difference);
66637         return difference;
66638     }
66639
66640
66641     // iD uses namespaced keys so multiple installations do not conflict
66642     function getKey(n) {
66643         return 'iD_' + window.location.origin + '_' + n;
66644     }
66645
66646
66647     var history = {
66648
66649         graph: function() {
66650             return stack$$1[index].graph;
66651         },
66652
66653
66654         base: function() {
66655             return stack$$1[0].graph;
66656         },
66657
66658
66659         merge: function(entities, extent$$1) {
66660             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
66661             tree$$1.rebase(entities, false);
66662
66663             dispatch$$1.call('change', this, undefined, extent$$1);
66664         },
66665
66666
66667         perform: function() {
66668             // complete any transition already in progress
66669             select(document).interrupt('history.perform');
66670
66671             var transitionable = false,
66672                 action0 = arguments[0];
66673
66674             if (arguments.length === 1 ||
66675                 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
66676                 transitionable = !!action0.transitionable;
66677             }
66678
66679             if (transitionable) {
66680                 var origArguments = arguments;
66681                 select(document)
66682                     .transition('history.perform')
66683                     .duration(duration)
66684                     .ease(linear$1)
66685                     .tween('history.tween', function() {
66686                         return function(t) {
66687                             if (t < 1) _overwrite([action0], t);
66688                         };
66689                     })
66690                     .on('start', function() {
66691                         _perform([action0], 0);
66692                     })
66693                     .on('end interrupt', function() {
66694                         _overwrite(origArguments, 1);
66695                     });
66696
66697             } else {
66698                 return _perform(arguments);
66699             }
66700         },
66701
66702
66703         replace: function() {
66704             select(document).interrupt('history.perform');
66705             return _replace(arguments, 1);
66706         },
66707
66708
66709         // Same as calling pop and then perform
66710         overwrite: function() {
66711             select(document).interrupt('history.perform');
66712             return _overwrite(arguments, 1);
66713         },
66714
66715
66716         pop: function() {
66717             select(document).interrupt('history.perform');
66718
66719             var previous = stack$$1[index].graph;
66720             if (index > 0) {
66721                 index--;
66722                 stack$$1.pop();
66723                 return change(previous);
66724             }
66725         },
66726
66727
66728         undo: function() {
66729             select(document).interrupt('history.perform');
66730
66731             var previous = stack$$1[index].graph;
66732
66733             // Pop to the next annotated state.
66734             while (index > 0) {
66735                 index--;
66736                 if (stack$$1[index].annotation) break;
66737             }
66738
66739             dispatch$$1.call('undone', this, stack$$1[index]);
66740             return change(previous);
66741         },
66742
66743
66744         redo: function() {
66745             select(document).interrupt('history.perform');
66746
66747             var previous = stack$$1[index].graph;
66748             while (index < stack$$1.length - 1) {
66749                 index++;
66750                 if (stack$$1[index].annotation) break;
66751             }
66752
66753             dispatch$$1.call('redone', this, stack$$1[index]);
66754             return change(previous);
66755         },
66756
66757
66758         undoAnnotation: function() {
66759             var i = index;
66760             while (i >= 0) {
66761                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66762                 i--;
66763             }
66764         },
66765
66766
66767         redoAnnotation: function() {
66768             var i = index + 1;
66769             while (i <= stack$$1.length - 1) {
66770                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66771                 i++;
66772             }
66773         },
66774
66775
66776         intersects: function(extent$$1) {
66777             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
66778         },
66779
66780
66781         difference: function() {
66782             var base = stack$$1[0].graph,
66783                 head = stack$$1[index].graph;
66784             return coreDifference(base, head);
66785         },
66786
66787
66788         changes: function(action) {
66789             var base = stack$$1[0].graph,
66790                 head = stack$$1[index].graph;
66791
66792             if (action) {
66793                 head = action(head);
66794             }
66795
66796             var difference = coreDifference(base, head);
66797
66798             return {
66799                 modified: difference.modified(),
66800                 created: difference.created(),
66801                 deleted: difference.deleted()
66802             };
66803         },
66804
66805
66806         validate: function(changes) {
66807             return lodash(Validations)
66808                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
66809                 .flatten()
66810                 .value();
66811         },
66812
66813
66814         hasChanges: function() {
66815             return this.difference().length() > 0;
66816         },
66817
66818
66819         imageryUsed: function(sources) {
66820             if (sources) {
66821                 imageryUsed = sources;
66822                 return history;
66823             } else {
66824                 return lodash(stack$$1.slice(1, index + 1))
66825                     .map('imageryUsed')
66826                     .flatten()
66827                     .uniq()
66828                     .without(undefined, 'Custom')
66829                     .value();
66830             }
66831         },
66832
66833
66834         reset: function() {
66835             stack$$1 = [{graph: coreGraph$$1()}];
66836             index = 0;
66837             tree$$1 = coreTree(stack$$1[0].graph);
66838             dispatch$$1.call('change');
66839             return history;
66840         },
66841
66842
66843         toJSON: function() {
66844             if (!this.hasChanges()) return;
66845
66846             var allEntities = {},
66847                 baseEntities = {},
66848                 base = stack$$1[0];
66849
66850             var s = stack$$1.map(function(i) {
66851                 var modified = [], deleted = [];
66852
66853                 lodash.forEach(i.graph.entities, function(entity, id) {
66854                     if (entity) {
66855                         var key = osmEntity$$1.key(entity);
66856                         allEntities[key] = entity;
66857                         modified.push(key);
66858                     } else {
66859                         deleted.push(id);
66860                     }
66861
66862                     // make sure that the originals of changed or deleted entities get merged
66863                     // into the base of the stack after restoring the data from JSON.
66864                     if (id in base.graph.entities) {
66865                         baseEntities[id] = base.graph.entities[id];
66866                     }
66867                     // get originals of parent entities too
66868                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
66869                         if (parentId in base.graph.entities) {
66870                             baseEntities[parentId] = base.graph.entities[parentId];
66871                         }
66872                     });
66873                 });
66874
66875                 var x = {};
66876
66877                 if (modified.length) x.modified = modified;
66878                 if (deleted.length) x.deleted = deleted;
66879                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
66880                 if (i.annotation) x.annotation = i.annotation;
66881
66882                 return x;
66883             });
66884
66885             return JSON.stringify({
66886                 version: 3,
66887                 entities: lodash.values(allEntities),
66888                 baseEntities: lodash.values(baseEntities),
66889                 stack: s,
66890                 nextIDs: osmEntity$$1.id.next,
66891                 index: index
66892             });
66893         },
66894
66895
66896         fromJSON: function(json$$1, loadChildNodes) {
66897             var h = JSON.parse(json$$1),
66898                 loadComplete = true;
66899
66900             osmEntity$$1.id.next = h.nextIDs;
66901             index = h.index;
66902
66903             if (h.version === 2 || h.version === 3) {
66904                 var allEntities = {};
66905
66906                 h.entities.forEach(function(entity) {
66907                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
66908                 });
66909
66910                 if (h.version === 3) {
66911                     // This merges originals for changed entities into the base of
66912                     // the stack even if the current stack doesn't have them (for
66913                     // example when iD has been restarted in a different region)
66914                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
66915                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
66916                     tree$$1.rebase(baseEntities, true);
66917
66918                     // When we restore a modified way, we also need to fetch any missing
66919                     // childnodes that would normally have been downloaded with it.. #2142
66920                     if (loadChildNodes) {
66921                         var missing =  lodash(baseEntities)
66922                                 .filter({ type: 'way' })
66923                                 .map('nodes')
66924                                 .flatten()
66925                                 .uniq()
66926                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
66927                                 .value();
66928
66929                         if (!lodash.isEmpty(missing)) {
66930                             loadComplete = false;
66931                             context.redrawEnable(false);
66932
66933                             var loading = uiLoading(context).blocking(true);
66934                             context.container().call(loading);
66935
66936                             var childNodesLoaded = function(err, result) {
66937                                 if (!err) {
66938                                     var visible = lodash.groupBy(result.data, 'visible');
66939                                     if (!lodash.isEmpty(visible.true)) {
66940                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
66941                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
66942                                         tree$$1.rebase(visible.true, true);
66943                                     }
66944
66945                                     // fetch older versions of nodes that were deleted..
66946                                     lodash.each(visible.false, function(entity) {
66947                                         context.connection()
66948                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
66949                                     });
66950                                 }
66951
66952                                 if (err || lodash.isEmpty(missing)) {
66953                                     loading.close();
66954                                     context.redrawEnable(true);
66955                                     dispatch$$1.call('change');
66956                                 }
66957                             };
66958
66959                             context.connection().loadMultiple(missing, childNodesLoaded);
66960                         }
66961                     }
66962                 }
66963
66964                 stack$$1 = h.stack.map(function(d) {
66965                     var entities = {}, entity;
66966
66967                     if (d.modified) {
66968                         d.modified.forEach(function(key) {
66969                             entity = allEntities[key];
66970                             entities[entity.id] = entity;
66971                         });
66972                     }
66973
66974                     if (d.deleted) {
66975                         d.deleted.forEach(function(id) {
66976                             entities[id] = undefined;
66977                         });
66978                     }
66979
66980                     return {
66981                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
66982                         annotation: d.annotation,
66983                         imageryUsed: d.imageryUsed
66984                     };
66985                 });
66986
66987             } else { // original version
66988                 stack$$1 = h.stack.map(function(d) {
66989                     var entities = {};
66990
66991                     for (var i in d.entities) {
66992                         var entity = d.entities[i];
66993                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
66994                     }
66995
66996                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
66997                     return d;
66998                 });
66999             }
67000
67001             if (loadComplete) {
67002                 dispatch$$1.call('change');
67003             }
67004
67005             return history;
67006         },
67007
67008
67009         save: function() {
67010             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
67011             return history;
67012         },
67013
67014
67015         clearSaved: function() {
67016             context.debouncedSave.cancel();
67017             if (lock.locked()) context.storage(getKey('saved_history'), null);
67018             return history;
67019         },
67020
67021
67022         lock: function() {
67023             return lock.lock();
67024         },
67025
67026
67027         unlock: function() {
67028             lock.unlock();
67029         },
67030
67031
67032         // is iD not open in another window and it detects that
67033         // there's a history stored in localStorage that's recoverable?
67034         restorableChanges: function() {
67035             return lock.locked() && !!context.storage(getKey('saved_history'));
67036         },
67037
67038
67039         // load history from a version stored in localStorage
67040         restore: function() {
67041             if (!lock.locked()) return;
67042
67043             var json$$1 = context.storage(getKey('saved_history'));
67044             if (json$$1) history.fromJSON(json$$1, true);
67045         },
67046
67047
67048         _getKey: getKey
67049
67050     };
67051
67052
67053     history.reset();
67054
67055     return utilRebind(history, dispatch$$1, 'on');
67056 }
67057
67058 function presetCollection(collection) {
67059     var maxSearchResults = 50,
67060         maxSuggestionResults = 10;
67061
67062     var presets = {
67063
67064         collection: collection,
67065
67066
67067         item: function(id) {
67068             return lodash.find(collection, function(d) {
67069                 return d.id === id;
67070             });
67071         },
67072
67073
67074         matchGeometry: function(geometry) {
67075             return presetCollection(collection.filter(function(d) {
67076                 return d.matchGeometry(geometry);
67077             }));
67078         },
67079
67080
67081         search: function(value, geometry) {
67082             if (!value) return this;
67083
67084             function leading(a) {
67085                 var index = a.indexOf(value);
67086                 return index === 0 || a[index - 1] === ' ';
67087             }
67088
67089             function suggestionName(name) {
67090                 var nameArray = name.split(' - ');
67091                 if (nameArray.length > 1) {
67092                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
67093                 }
67094                 return name.toLowerCase();
67095             }
67096
67097
67098             value = value.toLowerCase();
67099
67100             var searchable = lodash.filter(collection, function(a) {
67101                     return a.searchable !== false && a.suggestion !== true;
67102                 }),
67103                 suggestions = lodash.filter(collection, function(a) {
67104                     return a.suggestion === true;
67105                 });
67106
67107
67108             // matches value to preset.name
67109             var leading_name = lodash.filter(searchable, function(a) {
67110                     return leading(a.name().toLowerCase());
67111                 }).sort(function(a, b) {
67112                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
67113                     if (i === 0) return a.name().length - b.name().length;
67114                     else return i;
67115                 });
67116
67117             // matches value to preset.terms values
67118             var leading_terms = lodash.filter(searchable, function(a) {
67119                     return lodash.some(a.terms() || [], leading);
67120                 });
67121
67122             // matches value to preset.tags values
67123             var leading_tag_values = lodash.filter(searchable, function(a) {
67124                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
67125                 });
67126
67127
67128             // finds close matches to value in preset.name
67129             var similar_name = searchable.map(function(a) {
67130                     return {
67131                         preset: a,
67132                         dist: utilEditDistance(value, a.name())
67133                     };
67134                 }).filter(function(a) {
67135                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
67136                 }).sort(function(a, b) {
67137                     return a.dist - b.dist;
67138                 }).map(function(a) {
67139                     return a.preset;
67140                 });
67141
67142             // finds close matches to value in preset.terms
67143             var similar_terms = lodash.filter(searchable, function(a) {
67144                     return lodash.some(a.terms() || [], function(b) {
67145                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
67146                     });
67147                 });
67148
67149             var leading_suggestions = lodash.filter(suggestions, function(a) {
67150                     return leading(suggestionName(a.name()));
67151                 }).sort(function(a, b) {
67152                     a = suggestionName(a.name());
67153                     b = suggestionName(b.name());
67154                     var i = a.indexOf(value) - b.indexOf(value);
67155                     if (i === 0) return a.length - b.length;
67156                     else return i;
67157                 });
67158
67159             var similar_suggestions = suggestions.map(function(a) {
67160                     return {
67161                         preset: a,
67162                         dist: utilEditDistance(value, suggestionName(a.name()))
67163                     };
67164                 }).filter(function(a) {
67165                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
67166                 }).sort(function(a, b) {
67167                     return a.dist - b.dist;
67168                 }).map(function(a) {
67169                     return a.preset;
67170                 });
67171
67172             var other = presets.item(geometry);
67173
67174             var results = leading_name.concat(
67175                     leading_terms,
67176                     leading_tag_values,
67177                     leading_suggestions.slice(0, maxSuggestionResults + 5),
67178                     similar_name,
67179                     similar_terms,
67180                     similar_suggestions.slice(0, maxSuggestionResults)
67181                 ).slice(0, maxSearchResults - 1);
67182
67183             return presetCollection(lodash.uniq(results.concat(other)));
67184         }
67185     };
67186
67187
67188     return presets;
67189 }
67190
67191 function presetCategory(id, category, all) {
67192     category = lodash.clone(category);
67193
67194     category.id = id;
67195
67196
67197     category.members = presetCollection(category.members.map(function(id) {
67198         return all.item(id);
67199     }));
67200
67201
67202     category.matchGeometry = function(geometry) {
67203         return category.geometry.indexOf(geometry) >= 0;
67204     };
67205
67206
67207     category.matchScore = function() {
67208         return -1;
67209     };
67210
67211
67212     category.name = function() {
67213         return t('presets.categories.' + id + '.name', {'default': id});
67214     };
67215
67216
67217     category.terms = function() {
67218         return [];
67219     };
67220
67221
67222     return category;
67223 }
67224
67225 function presetField(id, field) {
67226     field = lodash.clone(field);
67227
67228     field.id = id;
67229
67230
67231     field.matchGeometry = function(geometry) {
67232         return !field.geometry || field.geometry === geometry;
67233     };
67234
67235
67236     field.t = function(scope, options) {
67237         return t('presets.fields.' + id + '.' + scope, options);
67238     };
67239
67240
67241     field.label = function() {
67242         return field.t('label', {'default': id});
67243     };
67244
67245
67246     var placeholder = field.placeholder;
67247     field.placeholder = function() {
67248         return field.t('placeholder', {'default': placeholder});
67249     };
67250
67251
67252     return field;
67253 }
67254
67255 function presetPreset(id, preset, fields) {
67256     preset = lodash.clone(preset);
67257
67258     preset.id = id;
67259     preset.fields = (preset.fields || []).map(getFields);
67260     preset.geometry = (preset.geometry || []);
67261
67262
67263     function getFields(f) {
67264         return fields[f];
67265     }
67266
67267
67268     preset.matchGeometry = function(geometry) {
67269         return preset.geometry.indexOf(geometry) >= 0;
67270     };
67271
67272
67273     var matchScore = preset.matchScore || 1;
67274     preset.matchScore = function(entity) {
67275         var tags = preset.tags,
67276             score = 0;
67277
67278         for (var t$$1 in tags) {
67279             if (entity.tags[t$$1] === tags[t$$1]) {
67280                 score += matchScore;
67281             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
67282                 score += matchScore / 2;
67283             } else {
67284                 return -1;
67285             }
67286         }
67287
67288         return score;
67289     };
67290
67291
67292     preset.t = function(scope, options) {
67293         return t('presets.presets.' + id + '.' + scope, options);
67294     };
67295
67296
67297     var name = preset.name || '';
67298     preset.name = function() {
67299         if (preset.suggestion) {
67300             id = id.split('/');
67301             id = id[0] + '/' + id[1];
67302             return name + ' - ' + t('presets.presets.' + id + '.name');
67303         }
67304         return preset.t('name', {'default': name});
67305     };
67306
67307
67308     preset.terms = function() {
67309         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
67310     };
67311
67312
67313     preset.isFallback = function() {
67314         var tagCount = Object.keys(preset.tags).length;
67315         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
67316     };
67317
67318
67319     preset.reference = function(geometry) {
67320         var key = Object.keys(preset.tags)[0],
67321             value = preset.tags[key];
67322
67323         if (geometry === 'relation' && key === 'type') {
67324             if (value in preset.tags) {
67325                 key = value;
67326                 value = preset.tags[key];
67327             } else {
67328                 return { rtype: value };
67329             }
67330         }
67331
67332         if (value === '*') {
67333             return { key: key };
67334         } else {
67335             return { key: key, value: value };
67336         }
67337     };
67338
67339
67340     var removeTags = preset.removeTags || preset.tags;
67341     preset.removeTags = function(tags, geometry) {
67342         tags = lodash.omit(tags, lodash.keys(removeTags));
67343
67344         for (var f in preset.fields) {
67345             var field = preset.fields[f];
67346             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
67347                 delete tags[field.key];
67348             }
67349         }
67350
67351         delete tags.area;
67352         return tags;
67353     };
67354
67355
67356     var applyTags = preset.addTags || preset.tags;
67357     preset.applyTags = function(tags, geometry) {
67358         var k;
67359
67360         tags = lodash.clone(tags);
67361
67362         for (k in applyTags) {
67363             if (applyTags[k] === '*') {
67364                 tags[k] = 'yes';
67365             } else {
67366                 tags[k] = applyTags[k];
67367             }
67368         }
67369
67370         // Add area=yes if necessary.
67371         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
67372         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
67373         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
67374         if (geometry === 'area') {
67375             var needsAreaTag = true;
67376             if (preset.geometry.indexOf('line') === -1) {
67377                 for (k in applyTags) {
67378                     if (k in areaKeys) {
67379                         needsAreaTag = false;
67380                         break;
67381                     }
67382                 }
67383             }
67384             if (needsAreaTag) {
67385                 tags.area = 'yes';
67386             }
67387         }
67388
67389         for (var f in preset.fields) {
67390             var field = preset.fields[f];
67391             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
67392                 tags[field.key] = field.default;
67393             }
67394         }
67395
67396         return tags;
67397     };
67398
67399
67400     return preset;
67401 }
67402
67403 function presetIndex() {
67404     // a presetCollection with methods for
67405     // loading new data and returning defaults
67406
67407     var all = presetCollection([]),
67408         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
67409         fields = {},
67410         universal = [],
67411         recent = presetCollection([]);
67412
67413     // Index of presets by (geometry, tag key).
67414     var index = {
67415         point: {},
67416         vertex: {},
67417         line: {},
67418         area: {},
67419         relation: {}
67420     };
67421
67422     all.match = function(entity, resolver) {
67423         var geometry = entity.geometry(resolver);
67424
67425         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
67426         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
67427             geometry = 'point';
67428         }
67429
67430         var geometryMatches = index[geometry],
67431             best = -1,
67432             match;
67433
67434         for (var k in entity.tags) {
67435             var keyMatches = geometryMatches[k];
67436             if (!keyMatches) continue;
67437
67438             for (var i = 0; i < keyMatches.length; i++) {
67439                 var score = keyMatches[i].matchScore(entity);
67440                 if (score > best) {
67441                     best = score;
67442                     match = keyMatches[i];
67443                 }
67444             }
67445         }
67446
67447         return match || all.item(geometry);
67448     };
67449
67450
67451     // Because of the open nature of tagging, iD will never have a complete
67452     // list of tags used in OSM, so we want it to have logic like "assume
67453     // that a closed way with an amenity tag is an area, unless the amenity
67454     // is one of these specific types". This function computes a structure
67455     // that allows testing of such conditions, based on the presets designated
67456     // as as supporting (or not supporting) the area geometry.
67457     //
67458     // The returned object L is a whitelist/blacklist of tags. A closed way
67459     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
67460     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
67461     // and the subkeys form the blacklist.
67462     all.areaKeys = function() {
67463         var areaKeys = {},
67464             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
67465             presets = lodash.reject(all.collection, 'suggestion');
67466
67467         // whitelist
67468         presets.forEach(function(d) {
67469             for (var key in d.tags) break;
67470             if (!key) return;
67471             if (ignore.indexOf(key) !== -1) return;
67472
67473             if (d.geometry.indexOf('area') !== -1) {
67474                 areaKeys[key] = areaKeys[key] || {};
67475             }
67476         });
67477
67478         // blacklist
67479         presets.forEach(function(d) {
67480             for (var key in d.tags) break;
67481             if (!key) return;
67482             if (ignore.indexOf(key) !== -1) return;
67483
67484             var value = d.tags[key];
67485             if (d.geometry.indexOf('area') === -1 &&
67486                 d.geometry.indexOf('line') !== -1 &&
67487                 key in areaKeys && value !== '*') {
67488                 areaKeys[key][value] = true;
67489             }
67490         });
67491
67492         return areaKeys;
67493     };
67494
67495
67496     all.init = function() {
67497         var d = data.presets;
67498
67499         if (d.fields) {
67500             lodash.forEach(d.fields, function(d, id) {
67501                 fields[id] = presetField(id, d);
67502                 if (d.universal) universal.push(fields[id]);
67503             });
67504         }
67505
67506         if (d.presets) {
67507             lodash.forEach(d.presets, function(d, id) {
67508                 all.collection.push(presetPreset(id, d, fields));
67509             });
67510         }
67511
67512         if (d.categories) {
67513             lodash.forEach(d.categories, function(d, id) {
67514                 all.collection.push(presetCategory(id, d, all));
67515             });
67516         }
67517
67518         if (d.defaults) {
67519             var getItem = lodash.bind(all.item, all);
67520             defaults = {
67521                 area: presetCollection(d.defaults.area.map(getItem)),
67522                 line: presetCollection(d.defaults.line.map(getItem)),
67523                 point: presetCollection(d.defaults.point.map(getItem)),
67524                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
67525                 relation: presetCollection(d.defaults.relation.map(getItem))
67526             };
67527         }
67528
67529         for (var i = 0; i < all.collection.length; i++) {
67530             var preset = all.collection[i],
67531                 geometry = preset.geometry;
67532
67533             for (var j = 0; j < geometry.length; j++) {
67534                 var g = index[geometry[j]];
67535                 for (var k in preset.tags) {
67536                     (g[k] = g[k] || []).push(preset);
67537                 }
67538             }
67539         }
67540
67541         return all;
67542     };
67543
67544     all.field = function(id) {
67545         return fields[id];
67546     };
67547
67548     all.universal = function() {
67549         return universal;
67550     };
67551
67552     all.defaults = function(geometry, n) {
67553         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
67554             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
67555         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
67556     };
67557
67558     all.choose = function(preset) {
67559         if (!preset.isFallback()) {
67560             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
67561         }
67562         return all;
67563     };
67564
67565     return all;
67566 }
67567
67568 var areaKeys = {};
67569
67570 function setAreaKeys(value) {
67571     areaKeys = value;
67572 }
67573
67574
67575 function coreContext() {
67576
67577     // create a special translation that contains the keys in place of the strings
67578     var tkeys = lodash.cloneDeep(en);
67579     var parents = [];
67580
67581     function traverser(v, k, obj) {
67582         parents.push(k);
67583         if (lodash.isObject(v)) {
67584             lodash.forOwn(v, traverser);
67585         } else if (lodash.isString(v)) {
67586             obj[k] = parents.join('.');
67587         }
67588         parents.pop();
67589     }
67590
67591     lodash.forOwn(tkeys, traverser);
67592     addTranslation('_tkeys_', tkeys);
67593
67594     addTranslation('en', en);
67595     setLocale('en');
67596
67597     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
67598         context = {};
67599
67600     // https://github.com/openstreetmap/iD/issues/772
67601     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
67602     var storage;
67603     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
67604     storage = storage || (function() {
67605         var s = {};
67606         return {
67607             getItem: function(k) { return s[k]; },
67608             setItem: function(k, v) { s[k] = v; },
67609             removeItem: function(k) { delete s[k]; }
67610         };
67611     })();
67612
67613     context.storage = function(k, v) {
67614         try {
67615             if (arguments.length === 1) return storage.getItem(k);
67616             else if (v === null) storage.removeItem(k);
67617             else storage.setItem(k, v);
67618         } catch (e) {
67619             // localstorage quota exceeded
67620             /* eslint-disable no-console */
67621             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
67622             /* eslint-enable no-console */
67623         }
67624     };
67625
67626
67627     /* Straight accessors. Avoid using these if you can. */
67628     var ui, connection, history;
67629     context.ui = function() { return ui; };
67630     context.connection = function() { return connection; };
67631     context.history = function() { return history; };
67632
67633
67634     /* Connection */
67635     function entitiesLoaded(err, result) {
67636         if (!err) history.merge(result.data, result.extent);
67637     }
67638
67639     context.preauth = function(options) {
67640         connection.switch(options);
67641         return context;
67642     };
67643
67644     context.loadTiles = function(projection, dimensions, callback) {
67645         function done(err, result) {
67646             entitiesLoaded(err, result);
67647             if (callback) callback(err, result);
67648         }
67649         connection.loadTiles(projection, dimensions, done);
67650     };
67651
67652     context.loadEntity = function(id, callback) {
67653         function done(err, result) {
67654             entitiesLoaded(err, result);
67655             if (callback) callback(err, result);
67656         }
67657         connection.loadEntity(id, done);
67658     };
67659
67660     context.zoomToEntity = function(id, zoomTo) {
67661         if (zoomTo !== false) {
67662             this.loadEntity(id, function(err, result) {
67663                 if (err) return;
67664                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
67665                 if (entity) { map$$1.zoomTo(entity); }
67666             });
67667         }
67668
67669         map$$1.on('drawn.zoomToEntity', function() {
67670             if (!context.hasEntity(id)) return;
67671             map$$1.on('drawn.zoomToEntity', null);
67672             context.on('enter.zoomToEntity', null);
67673             context.enter(modeSelect(context, [id]));
67674         });
67675
67676         context.on('enter.zoomToEntity', function() {
67677             if (mode.id !== 'browse') {
67678                 map$$1.on('drawn.zoomToEntity', null);
67679                 context.on('enter.zoomToEntity', null);
67680             }
67681         });
67682     };
67683
67684     var minEditableZoom = 16;
67685     context.minEditableZoom = function(_) {
67686         if (!arguments.length) return minEditableZoom;
67687         minEditableZoom = _;
67688         connection.tileZoom(_);
67689         return context;
67690     };
67691
67692
67693     /* History */
67694     var inIntro = false;
67695     context.inIntro = function(_) {
67696         if (!arguments.length) return inIntro;
67697         inIntro = _;
67698         return context;
67699     };
67700
67701     context.save = function() {
67702         // no history save, no message onbeforeunload
67703         if (inIntro || select('.modal').size()) return;
67704
67705         var canSave;
67706         if (mode && mode.id === 'save') {
67707             canSave = false;
67708         } else {
67709             canSave = context.selectedIDs().every(function(id) {
67710                 var entity = context.hasEntity(id);
67711                 return entity && !entity.isDegenerate();
67712             });
67713         }
67714
67715         if (canSave) {
67716             history.save();
67717         }
67718         if (history.hasChanges()) {
67719             return t('save.unsaved_changes');
67720         }
67721     };
67722
67723
67724     /* Graph */
67725     context.hasEntity = function(id) {
67726         return history.graph().hasEntity(id);
67727     };
67728     context.entity = function(id) {
67729         return history.graph().entity(id);
67730     };
67731     context.childNodes = function(way) {
67732         return history.graph().childNodes(way);
67733     };
67734     context.geometry = function(id) {
67735         return context.entity(id).geometry(history.graph());
67736     };
67737
67738
67739     /* Modes */
67740     var mode;
67741     context.mode = function() {
67742         return mode;
67743     };
67744     context.enter = function(newMode) {
67745         if (mode) {
67746             mode.exit();
67747             dispatch$$1.call('exit', this, mode);
67748         }
67749
67750         mode = newMode;
67751         mode.enter();
67752         dispatch$$1.call('enter', this, mode);
67753     };
67754
67755     context.selectedIDs = function() {
67756         if (mode && mode.selectedIDs) {
67757             return mode.selectedIDs();
67758         } else {
67759             return [];
67760         }
67761     };
67762
67763
67764     /* Behaviors */
67765     context.install = function(behavior) {
67766         context.surface().call(behavior);
67767     };
67768     context.uninstall = function(behavior) {
67769         context.surface().call(behavior.off);
67770     };
67771
67772
67773     /* Copy/Paste */
67774     var copyIDs = [], copyGraph;
67775     context.copyGraph = function() { return copyGraph; };
67776     context.copyIDs = function(_) {
67777         if (!arguments.length) return copyIDs;
67778         copyIDs = _;
67779         copyGraph = history.graph();
67780         return context;
67781     };
67782
67783
67784     /* Background */
67785     var background;
67786     context.background = function() { return background; };
67787
67788
67789     /* Features */
67790     var features;
67791     context.features = function() { return features; };
67792     context.hasHiddenConnections = function(id) {
67793         var graph = history.graph(),
67794             entity = graph.entity(id);
67795         return features.hasHiddenConnections(entity, graph);
67796     };
67797
67798
67799     /* Presets */
67800     var presets;
67801     context.presets = function() { return presets; };
67802
67803
67804     /* Map */
67805     var map$$1;
67806     context.map = function() { return map$$1; };
67807     context.layers = function() { return map$$1.layers; };
67808     context.surface = function() { return map$$1.surface; };
67809     context.editable = function() { return map$$1.editable(); };
67810
67811     context.surfaceRect = function() {
67812         // Work around a bug in Firefox.
67813         //   http://stackoverflow.com/questions/18153989/
67814         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
67815         return context.surface().node().parentNode.getBoundingClientRect();
67816     };
67817
67818
67819     /* Debug */
67820     var debugFlags = {
67821         tile: false,
67822         collision: false,
67823         imagery: false,
67824         imperial: false,
67825         driveLeft: false
67826     };
67827     context.debugFlags = function() {
67828         return debugFlags;
67829     };
67830     context.setDebug = function(flag, val) {
67831         if (arguments.length === 1) val = true;
67832         debugFlags[flag] = val;
67833         dispatch$$1.call('change');
67834         return context;
67835     };
67836     context.getDebug = function(flag) {
67837         return flag && debugFlags[flag];
67838     };
67839
67840
67841     /* Container */
67842     var container, embed;
67843     context.container = function(_) {
67844         if (!arguments.length) return container;
67845         container = _;
67846         container.classed('id-container', true);
67847         return context;
67848     };
67849     context.embed = function(_) {
67850         if (!arguments.length) return embed;
67851         embed = _;
67852         return context;
67853     };
67854
67855
67856     /* Assets */
67857     var assetPath = '';
67858     context.assetPath = function(_) {
67859         if (!arguments.length) return assetPath;
67860         assetPath = _;
67861         return context;
67862     };
67863
67864     var assetMap = {};
67865     context.assetMap = function(_) {
67866         if (!arguments.length) return assetMap;
67867         assetMap = _;
67868         return context;
67869     };
67870
67871     context.asset = function(_) {
67872         var filename = assetPath + _;
67873         return assetMap[filename] || filename;
67874     };
67875
67876     context.imagePath = function(_) {
67877         return context.asset('img/' + _);
67878     };
67879
67880
67881     /* locales */
67882     // `locale` variable contains a "requested locale".
67883     // It won't become the `currentLocale` until after loadLocale() is called.
67884     var locale, localePath;
67885
67886     context.locale = function(loc, path$$1) {
67887         if (!arguments.length) return currentLocale;
67888         locale = loc;
67889         localePath = path$$1;
67890         return context;
67891     };
67892
67893     context.loadLocale = function(callback) {
67894         if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
67895             localePath = localePath || context.asset('locales/' + locale + '.json');
67896             json(localePath, function(err, result) {
67897                 if (!err) {
67898                     addTranslation(locale, result[locale]);
67899                     setLocale(locale);
67900                     utilDetect(true);
67901                 }
67902                 if (callback) {
67903                     callback(err);
67904                 }
67905             });
67906         } else {
67907             if (locale) {
67908                 setLocale(locale);
67909                 utilDetect(true);
67910             }
67911             if (callback) {
67912                 callback();
67913             }
67914         }
67915     };
67916
67917
67918     /* reset (aka flush) */
67919     context.reset = context.flush = function() {
67920         context.debouncedSave.cancel();
67921         lodash.each(services, function(service) {
67922             if (service && typeof service.reset === 'function') {
67923                 service.reset(context);
67924             }
67925         });
67926         features.reset();
67927         history.reset();
67928         return context;
67929     };
67930
67931
67932     /* Init */
67933     context.version = '2.1.2';
67934
67935     context.projection = geoRawMercator();
67936
67937     locale = utilDetect().locale;
67938     if (locale && !dataLocales.hasOwnProperty(locale)) {
67939         locale = locale.split('-')[0];
67940     }
67941
67942     history = coreHistory(context);
67943     context.graph = history.graph;
67944     context.changes = history.changes;
67945     context.intersects = history.intersects;
67946
67947     // Debounce save, since it's a synchronous localStorage write,
67948     // and history changes can happen frequently (e.g. when dragging).
67949     context.debouncedSave = lodash.debounce(context.save, 350);
67950     function withDebouncedSave(fn) {
67951         return function() {
67952             var result = fn.apply(history, arguments);
67953             context.debouncedSave();
67954             return result;
67955         };
67956     }
67957
67958     context.perform = withDebouncedSave(history.perform);
67959     context.replace = withDebouncedSave(history.replace);
67960     context.pop = withDebouncedSave(history.pop);
67961     context.overwrite = withDebouncedSave(history.overwrite);
67962     context.undo = withDebouncedSave(history.undo);
67963     context.redo = withDebouncedSave(history.redo);
67964
67965     ui = uiInit(context);
67966
67967     connection = services.osm;
67968     background = rendererBackground(context);
67969     features = rendererFeatures(context);
67970     presets = presetIndex();
67971
67972     map$$1 = rendererMap(context);
67973     context.mouse = map$$1.mouse;
67974     context.extent = map$$1.extent;
67975     context.pan = map$$1.pan;
67976     context.zoomIn = map$$1.zoomIn;
67977     context.zoomOut = map$$1.zoomOut;
67978     context.zoomInFurther = map$$1.zoomInFurther;
67979     context.zoomOutFurther = map$$1.zoomOutFurther;
67980     context.redrawEnable = map$$1.redrawEnable;
67981
67982     lodash.each(services, function(service) {
67983         if (service && typeof service.init === 'function') {
67984             service.init(context);
67985         }
67986     });
67987
67988     background.init();
67989     presets.init();
67990     areaKeys = presets.areaKeys();
67991
67992
67993     return utilRebind(context, dispatch$$1, 'on');
67994 }
67995
67996 function osmWay() {
67997     if (!(this instanceof osmWay)) {
67998         return (new osmWay()).initialize(arguments);
67999     } else if (arguments.length) {
68000         this.initialize(arguments);
68001     }
68002 }
68003
68004
68005 osmEntity$$1.way = osmWay;
68006
68007 osmWay.prototype = Object.create(osmEntity$$1.prototype);
68008
68009
68010 lodash.extend(osmWay.prototype, {
68011     type: 'way',
68012     nodes: [],
68013
68014
68015     copy: function(resolver, copies) {
68016         if (copies[this.id])
68017             return copies[this.id];
68018
68019         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
68020
68021         var nodes = this.nodes.map(function(id) {
68022             return resolver.entity(id).copy(resolver, copies).id;
68023         });
68024
68025         copy = copy.update({ nodes: nodes });
68026         copies[this.id] = copy;
68027
68028         return copy;
68029     },
68030
68031
68032     extent: function(resolver) {
68033         return resolver.transient(this, 'extent', function() {
68034             var extent$$1 = geoExtent$$1();
68035             for (var i = 0; i < this.nodes.length; i++) {
68036                 var node = resolver.hasEntity(this.nodes[i]);
68037                 if (node) {
68038                     extent$$1._extend(node.extent());
68039                 }
68040             }
68041             return extent$$1;
68042         });
68043     },
68044
68045
68046     first: function() {
68047         return this.nodes[0];
68048     },
68049
68050
68051     last: function() {
68052         return this.nodes[this.nodes.length - 1];
68053     },
68054
68055
68056     contains: function(node) {
68057         return this.nodes.indexOf(node) >= 0;
68058     },
68059
68060
68061     affix: function(node) {
68062         if (this.nodes[0] === node) return 'prefix';
68063         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
68064     },
68065
68066
68067     layer: function() {
68068         // explicit layer tag, clamp between -10, 10..
68069         if (isFinite(this.tags.layer)) {
68070             return Math.max(-10, Math.min(+(this.tags.layer), 10));
68071         }
68072
68073         // implied layer tag..
68074         if (this.tags.location === 'overground') return 1;
68075         if (this.tags.location === 'underground') return -1;
68076         if (this.tags.location === 'underwater') return -10;
68077
68078         if (this.tags.power === 'line') return 10;
68079         if (this.tags.power === 'minor_line') return 10;
68080         if (this.tags.aerialway) return 10;
68081         if (this.tags.bridge) return 1;
68082         if (this.tags.cutting) return -1;
68083         if (this.tags.tunnel) return -1;
68084         if (this.tags.waterway) return -1;
68085         if (this.tags.man_made === 'pipeline') return -10;
68086         if (this.tags.boundary) return -10;
68087         return 0;
68088     },
68089
68090
68091     isOneWay: function() {
68092         // explicit oneway tag..
68093         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
68094         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
68095
68096         // implied oneway tag..
68097         for (var key in this.tags) {
68098             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
68099                 return true;
68100         }
68101         return false;
68102     },
68103
68104
68105     lanes: function() {
68106         return osmLanes(this);
68107     },
68108
68109
68110     isClosed: function() {
68111         return this.nodes.length > 1 && this.first() === this.last();
68112     },
68113
68114
68115     isConvex: function(resolver) {
68116         if (!this.isClosed() || this.isDegenerate()) return null;
68117
68118         var nodes = lodash.uniq(resolver.childNodes(this)),
68119             coords = lodash.map(nodes, 'loc'),
68120             curr = 0, prev = 0;
68121
68122         for (var i = 0; i < coords.length; i++) {
68123             var o = coords[(i+1) % coords.length],
68124                 a = coords[i],
68125                 b = coords[(i+2) % coords.length],
68126                 res = geoCross(o, a, b);
68127
68128             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
68129             if (curr === 0) {
68130                 continue;
68131             } else if (prev && curr !== prev) {
68132                 return false;
68133             }
68134             prev = curr;
68135         }
68136         return true;
68137     },
68138
68139
68140     isArea: function() {
68141         if (this.tags.area === 'yes')
68142             return true;
68143         if (!this.isClosed() || this.tags.area === 'no')
68144             return false;
68145         for (var key in this.tags) {
68146             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
68147                 return true;
68148             }
68149         }
68150         return false;
68151     },
68152
68153
68154     isDegenerate: function() {
68155         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
68156     },
68157
68158
68159     areAdjacent: function(n1, n2) {
68160         for (var i = 0; i < this.nodes.length; i++) {
68161             if (this.nodes[i] === n1) {
68162                 if (this.nodes[i - 1] === n2) return true;
68163                 if (this.nodes[i + 1] === n2) return true;
68164             }
68165         }
68166         return false;
68167     },
68168
68169
68170     geometry: function(graph) {
68171         return graph.transient(this, 'geometry', function() {
68172             return this.isArea() ? 'area' : 'line';
68173         });
68174     },
68175
68176
68177     // If this way is not closed, append the beginning node to the end of the nodelist to close it.
68178     close: function() {
68179         if (this.isClosed() || !this.nodes.length) return this;
68180
68181         var nodes = this.nodes.slice();
68182         nodes = nodes.filter(noRepeatNodes);
68183         nodes.push(nodes[0]);
68184         return this.update({ nodes: nodes });
68185     },
68186
68187
68188     // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
68189     unclose: function() {
68190         if (!this.isClosed()) return this;
68191
68192         var nodes = this.nodes.slice(),
68193             connector = this.first(),
68194             i = nodes.length - 1;
68195
68196         // remove trailing connectors..
68197         while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68198             nodes.splice(i, 1);
68199             i = nodes.length - 1;
68200         }
68201
68202         nodes = nodes.filter(noRepeatNodes);
68203         return this.update({ nodes: nodes });
68204     },
68205
68206
68207     // Adds a node (id) in front of the node which is currently at position index.
68208     // If index is undefined, the node will be added to the end of the way for linear ways,
68209     //   or just before the final connecting node for circular ways.
68210     // Consecutive duplicates are eliminated including existing ones.
68211     // Circularity is always preserved when adding a node.
68212     addNode: function(id, index) {
68213         var nodes = this.nodes.slice(),
68214             isClosed = this.isClosed(),
68215             max$$1 = isClosed ? nodes.length - 1 : nodes.length;
68216
68217         if (index === undefined) {
68218             index = max$$1;
68219         }
68220
68221         if (index < 0 || index > max$$1) {
68222             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68223         }
68224
68225         // If this is a closed way, remove all connector nodes except the first one
68226         // (there may be duplicates) and adjust index if necessary..
68227         if (isClosed) {
68228             var connector = this.first();
68229
68230             // leading connectors..
68231             var i = 1;
68232             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68233                 nodes.splice(i, 1);
68234                 if (index > i) index--;
68235             }
68236
68237             // trailing connectors..
68238             i = nodes.length - 1;
68239             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68240                 nodes.splice(i, 1);
68241                 if (index > i) index--;
68242                 i = nodes.length - 1;
68243             }
68244         }
68245
68246         nodes.splice(index, 0, id);
68247         nodes = nodes.filter(noRepeatNodes);
68248
68249         // If the way was closed before, append a connector node to keep it closed..
68250         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68251             nodes.push(nodes[0]);
68252         }
68253
68254         return this.update({ nodes: nodes });
68255     },
68256
68257
68258     // Replaces the node which is currently at position index with the given node (id).
68259     // Consecutive duplicates are eliminated including existing ones.
68260     // Circularity is preserved when updating a node.
68261     updateNode: function(id, index) {
68262         var nodes = this.nodes.slice(),
68263             isClosed = this.isClosed(),
68264             max$$1 = nodes.length - 1;
68265
68266         if (index === undefined || index < 0 || index > max$$1) {
68267             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68268         }
68269
68270         // If this is a closed way, remove all connector nodes except the first one
68271         // (there may be duplicates) and adjust index if necessary..
68272         if (isClosed) {
68273             var connector = this.first();
68274
68275             // leading connectors..
68276             var i = 1;
68277             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68278                 nodes.splice(i, 1);
68279                 if (index > i) index--;
68280             }
68281
68282             // trailing connectors..
68283             i = nodes.length - 1;
68284             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68285                 nodes.splice(i, 1);
68286                 if (index === i) index = 0;  // update leading connector instead
68287                 i = nodes.length - 1;
68288             }
68289         }
68290
68291         nodes.splice(index, 1, id);
68292         nodes = nodes.filter(noRepeatNodes);
68293
68294         // If the way was closed before, append a connector node to keep it closed..
68295         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68296             nodes.push(nodes[0]);
68297         }
68298
68299         return this.update({nodes: nodes});
68300     },
68301
68302
68303     // Replaces each occurrence of node id needle with replacement.
68304     // Consecutive duplicates are eliminated including existing ones.
68305     // Circularity is preserved.
68306     replaceNode: function(needle, replacement) {
68307         var nodes = this.nodes.slice(),
68308             isClosed = this.isClosed();
68309
68310         for (var i = 0; i < nodes.length; i++) {
68311             if (nodes[i] === needle) {
68312                 nodes[i] = replacement;
68313             }
68314         }
68315
68316         nodes = nodes.filter(noRepeatNodes);
68317
68318         // If the way was closed before, append a connector node to keep it closed..
68319         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68320             nodes.push(nodes[0]);
68321         }
68322
68323         return this.update({nodes: nodes});
68324     },
68325
68326
68327     // Removes each occurrence of node id needle with replacement.
68328     // Consecutive duplicates are eliminated including existing ones.
68329     // Circularity is preserved.
68330     removeNode: function(id) {
68331         var nodes = this.nodes.slice(),
68332             isClosed = this.isClosed();
68333
68334         nodes = nodes
68335             .filter(function(node) { return node !== id; })
68336             .filter(noRepeatNodes);
68337
68338         // If the way was closed before, append a connector node to keep it closed..
68339         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68340             nodes.push(nodes[0]);
68341         }
68342
68343         return this.update({nodes: nodes});
68344     },
68345
68346
68347     asJXON: function(changeset_id) {
68348         var r = {
68349             way: {
68350                 '@id': this.osmId(),
68351                 '@version': this.version || 0,
68352                 nd: lodash.map(this.nodes, function(id) {
68353                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
68354                 }),
68355                 tag: lodash.map(this.tags, function(v, k) {
68356                     return { keyAttributes: { k: k, v: v } };
68357                 })
68358             }
68359         };
68360         if (changeset_id) {
68361             r.way['@changeset'] = changeset_id;
68362         }
68363         return r;
68364     },
68365
68366
68367     asGeoJSON: function(resolver) {
68368         return resolver.transient(this, 'GeoJSON', function() {
68369             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
68370             if (this.isArea() && this.isClosed()) {
68371                 return {
68372                     type: 'Polygon',
68373                     coordinates: [coordinates]
68374                 };
68375             } else {
68376                 return {
68377                     type: 'LineString',
68378                     coordinates: coordinates
68379                 };
68380             }
68381         });
68382     },
68383
68384
68385     area: function(resolver) {
68386         return resolver.transient(this, 'area', function() {
68387             var nodes = resolver.childNodes(this);
68388
68389             var json$$1 = {
68390                 type: 'Polygon',
68391                 coordinates: [lodash.map(nodes, 'loc')]
68392             };
68393
68394             if (!this.isClosed() && nodes.length) {
68395                 json$$1.coordinates[0].push(nodes[0].loc);
68396             }
68397
68398             var area$$1 = area(json$$1);
68399
68400             // Heuristic for detecting counterclockwise winding order. Assumes
68401             // that OpenStreetMap polygons are not hemisphere-spanning.
68402             if (area$$1 > 2 * Math.PI) {
68403                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
68404                 area$$1 = area(json$$1);
68405             }
68406
68407             return isNaN(area$$1) ? 0 : area$$1;
68408         });
68409     }
68410 });
68411
68412
68413 // Filter function to eliminate consecutive duplicates.
68414 function noRepeatNodes(node, i, arr) {
68415     return i === 0 || node !== arr[i - 1];
68416 }
68417
68418 function osmTurn(turn) {
68419     if (!(this instanceof osmTurn))
68420         return new osmTurn(turn);
68421     lodash.extend(this, turn);
68422 }
68423
68424
68425 function osmIntersection(graph, vertexId) {
68426     var vertex = graph.entity(vertexId),
68427         parentWays = graph.parentWays(vertex),
68428         coincident = [],
68429         highways = {};
68430
68431     function addHighway(way, adjacentNodeId) {
68432         if (highways[adjacentNodeId]) {
68433             coincident.push(adjacentNodeId);
68434         } else {
68435             highways[adjacentNodeId] = way;
68436         }
68437     }
68438
68439     // Pre-split ways that would need to be split in
68440     // order to add a restriction. The real split will
68441     // happen when the restriction is added.
68442     parentWays.forEach(function(way) {
68443         if (!way.tags.highway || way.isArea() || way.isDegenerate())
68444             return;
68445
68446         var isFirst = (vertexId === way.first()),
68447             isLast = (vertexId === way.last()),
68448             isAffix = (isFirst || isLast),
68449             isClosingNode = (isFirst && isLast);
68450
68451         if (isAffix && !isClosingNode) {
68452             var index = (isFirst ? 1 : way.nodes.length - 2);
68453             addHighway(way, way.nodes[index]);
68454
68455         } else {
68456             var splitIndex, wayA, wayB, indexA, indexB;
68457             if (isClosingNode) {
68458                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
68459                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
68460                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68461                 indexA = 1;
68462                 indexB = way.nodes.length - 2;
68463             } else {
68464                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
68465                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
68466                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68467                 indexA = splitIndex - 1;
68468                 indexB = splitIndex + 1;
68469             }
68470             graph = graph.replace(wayA).replace(wayB);
68471             addHighway(wayA, way.nodes[indexA]);
68472             addHighway(wayB, way.nodes[indexB]);
68473         }
68474     });
68475
68476     // remove any ways from this intersection that are coincident
68477     // (i.e. any adjacent node used by more than one intersecting way)
68478     coincident.forEach(function (n) {
68479         delete highways[n];
68480     });
68481
68482
68483     var intersection = {
68484         highways: highways,
68485         ways: lodash.values(highways),
68486         graph: graph
68487     };
68488
68489
68490     intersection.adjacentNodeId = function(fromWayId) {
68491         return lodash.find(lodash.keys(highways), function(k) {
68492             return highways[k].id === fromWayId;
68493         });
68494     };
68495
68496
68497     intersection.turns = function(fromNodeId) {
68498         var start = highways[fromNodeId];
68499         if (!start)
68500             return [];
68501
68502         if (start.first() === vertex.id && start.tags.oneway === 'yes')
68503             return [];
68504         if (start.last() === vertex.id && start.tags.oneway === '-1')
68505             return [];
68506
68507         function withRestriction(turn) {
68508             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
68509                 if (relation.tags.type !== 'restriction')
68510                     return;
68511
68512                 var f = relation.memberByRole('from'),
68513                     t = relation.memberByRole('to'),
68514                     v = relation.memberByRole('via');
68515
68516                 if (f && f.id === turn.from.way &&
68517                     v && v.id === turn.via.node &&
68518                     t && t.id === turn.to.way) {
68519                     turn.restriction = relation.id;
68520                 } else if (/^only_/.test(relation.tags.restriction) &&
68521                     f && f.id === turn.from.way &&
68522                     v && v.id === turn.via.node &&
68523                     t && t.id !== turn.to.way) {
68524                     turn.restriction = relation.id;
68525                     turn.indirect_restriction = true;
68526                 }
68527             });
68528
68529             return osmTurn(turn);
68530         }
68531
68532
68533         var from = {
68534                 node: fromNodeId,
68535                 way: start.id.split(/-(a|b)/)[0]
68536             },
68537             via = { node: vertex.id },
68538             turns = [];
68539
68540         lodash.each(highways, function(end, adjacentNodeId) {
68541             if (end === start)
68542                 return;
68543
68544             // backward
68545             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
68546                 turns.push(withRestriction({
68547                     from: from,
68548                     via: via,
68549                     to: {
68550                         node: adjacentNodeId,
68551                         way: end.id.split(/-(a|b)/)[0]
68552                     }
68553                 }));
68554             }
68555
68556             // forward
68557             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
68558                 turns.push(withRestriction({
68559                     from: from,
68560                     via: via,
68561                     to: {
68562                         node: adjacentNodeId,
68563                         way: end.id.split(/-(a|b)/)[0]
68564                     }
68565                 }));
68566             }
68567
68568         });
68569
68570         // U-turn
68571         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
68572             turns.push(withRestriction({
68573                 from: from,
68574                 via: via,
68575                 to: from,
68576                 u: true
68577             }));
68578         }
68579
68580         return turns;
68581     };
68582
68583     return intersection;
68584 }
68585
68586
68587 function osmInferRestriction(graph, from, via, to, projection) {
68588     var fromWay = graph.entity(from.way),
68589         fromNode = graph.entity(from.node),
68590         toWay = graph.entity(to.way),
68591         toNode = graph.entity(to.node),
68592         viaNode = graph.entity(via.node),
68593         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
68594             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
68595         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
68596             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
68597         angle = geoAngle(viaNode, fromNode, projection) -
68598                 geoAngle(viaNode, toNode, projection);
68599
68600     angle = angle * 180 / Math.PI;
68601
68602     while (angle < 0)
68603         angle += 360;
68604
68605     if (fromNode === toNode)
68606         return 'no_u_turn';
68607     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
68608         return 'no_u_turn';
68609     if (angle < 158)
68610         return 'no_right_turn';
68611     if (angle > 202)
68612         return 'no_left_turn';
68613
68614     return 'no_straight_on';
68615 }
68616
68617 function actionAddMember(relationId, member, memberIndex) {
68618     return function(graph) {
68619         var relation = graph.entity(relationId);
68620
68621         if (isNaN(memberIndex) && member.type === 'way') {
68622             var members = relation.indexedMembers();
68623             members.push(member);
68624
68625             var joined = osmJoinWays(members, graph);
68626             for (var i = 0; i < joined.length; i++) {
68627                 var segment = joined[i];
68628                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
68629                     if (segment[j] !== member)
68630                         continue;
68631
68632                     if (j === 0) {
68633                         memberIndex = segment[j + 1].index;
68634                     } else if (j === segment.length - 1) {
68635                         memberIndex = segment[j - 1].index + 1;
68636                     } else {
68637                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
68638                     }
68639                 }
68640             }
68641         }
68642
68643         return graph.replace(relation.addMember(member, memberIndex));
68644     };
68645 }
68646
68647 function actionAddMidpoint(midpoint, node) {
68648     return function(graph) {
68649         graph = graph.replace(node.move(midpoint.loc));
68650
68651         var parents = lodash.intersection(
68652             graph.parentWays(graph.entity(midpoint.edge[0])),
68653             graph.parentWays(graph.entity(midpoint.edge[1])));
68654
68655         parents.forEach(function(way) {
68656             for (var i = 0; i < way.nodes.length - 1; i++) {
68657                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
68658                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
68659
68660                     // Add only one midpoint on doubled-back segments,
68661                     // turning them into self-intersections.
68662                     return;
68663                 }
68664             }
68665         });
68666
68667         return graph;
68668     };
68669 }
68670
68671 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
68672 function actionAddVertex(wayId, nodeId, index) {
68673     return function(graph) {
68674         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
68675     };
68676 }
68677
68678 function actionChangeMember(relationId, member, memberIndex) {
68679     return function(graph) {
68680         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
68681     };
68682 }
68683
68684 function actionChangePreset(entityId, oldPreset, newPreset) {
68685     return function(graph) {
68686         var entity = graph.entity(entityId),
68687             geometry = entity.geometry(graph),
68688             tags = entity.tags;
68689
68690         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
68691         if (newPreset) tags = newPreset.applyTags(tags, geometry);
68692
68693         return graph.replace(entity.update({tags: tags}));
68694     };
68695 }
68696
68697 function actionChangeTags(entityId, tags) {
68698     return function(graph) {
68699         var entity = graph.entity(entityId);
68700         return graph.replace(entity.update({tags: tags}));
68701     };
68702 }
68703
68704 function actionCircularize(wayId, projection, maxAngle) {
68705     maxAngle = (maxAngle || 20) * Math.PI / 180;
68706
68707
68708     var action = function(graph, t) {
68709         if (t === null || !isFinite(t)) t = 1;
68710         t = Math.min(Math.max(+t, 0), 1);
68711
68712         var way = graph.entity(wayId),
68713             origNodes = {};
68714
68715         graph.childNodes(way).forEach(function(node) {
68716             if (!origNodes[node.id]) origNodes[node.id] = node;
68717         });
68718
68719         if (!way.isConvex(graph)) {
68720             graph = action.makeConvex(graph);
68721         }
68722
68723         var nodes = lodash.uniq(graph.childNodes(way)),
68724             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
68725             points = nodes.map(function(n) { return projection(n.loc); }),
68726             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
68727             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
68728             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
68729             sign = d3polygonArea(points) > 0 ? 1 : -1,
68730             ids;
68731
68732         // we need atleast two key nodes for the algorithm to work
68733         if (!keyNodes.length) {
68734             keyNodes = [nodes[0]];
68735             keyPoints = [points[0]];
68736         }
68737
68738         if (keyNodes.length === 1) {
68739             var index = nodes.indexOf(keyNodes[0]),
68740                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
68741
68742             keyNodes.push(nodes[oppositeIndex]);
68743             keyPoints.push(points[oppositeIndex]);
68744         }
68745
68746         // key points and nodes are those connected to the ways,
68747         // they are projected onto the circle, inbetween nodes are moved
68748         // to constant intervals between key nodes, extra inbetween nodes are
68749         // added if necessary.
68750         for (var i = 0; i < keyPoints.length; i++) {
68751             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
68752                 startNode = keyNodes[i],
68753                 endNode = keyNodes[nextKeyNodeIndex],
68754                 startNodeIndex = nodes.indexOf(startNode),
68755                 endNodeIndex = nodes.indexOf(endNode),
68756                 numberNewPoints = -1,
68757                 indexRange = endNodeIndex - startNodeIndex,
68758                 nearNodes = {},
68759                 inBetweenNodes = [],
68760                 startAngle, endAngle, totalAngle, eachAngle,
68761                 angle, loc, node, origNode, j;
68762
68763             if (indexRange < 0) {
68764                 indexRange += nodes.length;
68765             }
68766
68767             // position this key node
68768             var distance = geoEuclideanDistance(centroid, keyPoints[i]);
68769             if (distance === 0) { distance = 1e-4; }
68770             keyPoints[i] = [
68771                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
68772                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius
68773             ];
68774             loc = projection.invert(keyPoints[i]);
68775             node = keyNodes[i];
68776             origNode = origNodes[node.id];
68777             node = node.move(geoInterp(origNode.loc, loc, t));
68778             graph = graph.replace(node);
68779
68780             // figure out the between delta angle we want to match to
68781             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
68782             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
68783             totalAngle = endAngle - startAngle;
68784
68785             // detects looping around -pi/pi
68786             if (totalAngle * sign > 0) {
68787                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
68788             }
68789
68790             do {
68791                 numberNewPoints++;
68792                 eachAngle = totalAngle / (indexRange + numberNewPoints);
68793             } while (Math.abs(eachAngle) > maxAngle);
68794
68795
68796             // move existing nodes
68797             for (j = 1; j < indexRange; j++) {
68798                 angle = startAngle + j * eachAngle;
68799                 loc = projection.invert([
68800                     centroid[0] + Math.cos(angle) * radius,
68801                     centroid[1] + Math.sin(angle) * radius
68802                 ]);
68803
68804                 node = nodes[(j + startNodeIndex) % nodes.length];
68805                 origNode = origNodes[node.id];
68806                 nearNodes[node.id] = angle;
68807
68808                 node = node.move(geoInterp(origNode.loc, loc, t));
68809                 graph = graph.replace(node);
68810             }
68811
68812             // add new inbetween nodes if necessary
68813             for (j = 0; j < numberNewPoints; j++) {
68814                 angle = startAngle + (indexRange + j) * eachAngle;
68815                 loc = projection.invert([
68816                     centroid[0] + Math.cos(angle) * radius,
68817                     centroid[1] + Math.sin(angle) * radius
68818                 ]);
68819
68820                 // choose a nearnode to use as the original
68821                 var min$$1 = Infinity;
68822                 for (var nodeId in nearNodes) {
68823                     var nearAngle = nearNodes[nodeId],
68824                         dist = Math.abs(nearAngle - angle);
68825                     if (dist < min$$1) {
68826                         dist = min$$1;
68827                         origNode = origNodes[nodeId];
68828                     }
68829                 }
68830
68831                 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
68832                 graph = graph.replace(node);
68833
68834                 nodes.splice(endNodeIndex + j, 0, node);
68835                 inBetweenNodes.push(node.id);
68836             }
68837
68838             // Check for other ways that share these keyNodes..
68839             // If keyNodes are adjacent in both ways,
68840             // we can add inBetween nodes to that shared way too..
68841             if (indexRange === 1 && inBetweenNodes.length) {
68842                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
68843                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
68844                     wayDirection1 = (endIndex1 - startIndex1);
68845                 if (wayDirection1 < -1) { wayDirection1 = 1; }
68846
68847                 /* eslint-disable no-loop-func */
68848                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
68849                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
68850                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
68851                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
68852                             wayDirection2 = (endIndex2 - startIndex2),
68853                             insertAt = endIndex2;
68854                         if (wayDirection2 < -1) { wayDirection2 = 1; }
68855
68856                         if (wayDirection1 !== wayDirection2) {
68857                             inBetweenNodes.reverse();
68858                             insertAt = startIndex2;
68859                         }
68860                         for (j = 0; j < inBetweenNodes.length; j++) {
68861                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
68862                         }
68863                         graph = graph.replace(sharedWay);
68864                     }
68865                 });
68866                 /* eslint-enable no-loop-func */
68867             }
68868
68869         }
68870
68871         // update the way to have all the new nodes
68872         ids = nodes.map(function(n) { return n.id; });
68873         ids.push(ids[0]);
68874
68875         way = way.update({nodes: ids});
68876         graph = graph.replace(way);
68877
68878         return graph;
68879     };
68880
68881
68882     action.makeConvex = function(graph) {
68883         var way = graph.entity(wayId),
68884             nodes = lodash.uniq(graph.childNodes(way)),
68885             points = nodes.map(function(n) { return projection(n.loc); }),
68886             sign = d3polygonArea(points) > 0 ? 1 : -1,
68887             hull = d3polygonHull(points);
68888
68889         // D3 convex hulls go counterclockwise..
68890         if (sign === -1) {
68891             nodes.reverse();
68892             points.reverse();
68893         }
68894
68895         for (var i = 0; i < hull.length - 1; i++) {
68896             var startIndex = points.indexOf(hull[i]),
68897                 endIndex = points.indexOf(hull[i+1]),
68898                 indexRange = (endIndex - startIndex);
68899
68900             if (indexRange < 0) {
68901                 indexRange += nodes.length;
68902             }
68903
68904             // move interior nodes to the surface of the convex hull..
68905             for (var j = 1; j < indexRange; j++) {
68906                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
68907                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
68908                 graph = graph.replace(node);
68909             }
68910         }
68911         return graph;
68912     };
68913
68914
68915     action.disabled = function(graph) {
68916         if (!graph.entity(wayId).isClosed())
68917             return 'not_closed';
68918     };
68919
68920
68921     action.transitionable = true;
68922
68923
68924     return action;
68925 }
68926
68927 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
68928 function actionDeleteWay(wayId) {
68929
68930
68931     function canDeleteNode(node, graph) {
68932         return !graph.parentWays(node).length &&
68933             !graph.parentRelations(node).length &&
68934             !node.hasInterestingTags();
68935     }
68936
68937
68938     var action = function(graph) {
68939         var way = graph.entity(wayId);
68940
68941         graph.parentRelations(way)
68942             .forEach(function(parent) {
68943                 parent = parent.removeMembersWithID(wayId);
68944                 graph = graph.replace(parent);
68945
68946                 if (parent.isDegenerate()) {
68947                     graph = actionDeleteRelation(parent.id)(graph);
68948                 }
68949             });
68950
68951         lodash.uniq(way.nodes).forEach(function(nodeId) {
68952             graph = graph.replace(way.removeNode(nodeId));
68953
68954             var node = graph.entity(nodeId);
68955             if (canDeleteNode(node, graph)) {
68956                 graph = graph.remove(node);
68957             }
68958         });
68959
68960         return graph.remove(way);
68961     };
68962
68963
68964     return action;
68965 }
68966
68967 function actionDeleteMultiple(ids) {
68968     var actions = {
68969         way: actionDeleteWay,
68970         node: actionDeleteNode,
68971         relation: actionDeleteRelation
68972     };
68973
68974
68975     var action = function(graph) {
68976         ids.forEach(function(id) {
68977             if (graph.hasEntity(id)) { // It may have been deleted aready.
68978                 graph = actions[graph.entity(id).type](id)(graph);
68979             }
68980         });
68981
68982         return graph;
68983     };
68984
68985
68986     return action;
68987 }
68988
68989 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
68990 function actionDeleteRelation(relationId) {
68991
68992
68993     function canDeleteEntity(entity, graph) {
68994         return !graph.parentWays(entity).length &&
68995             !graph.parentRelations(entity).length &&
68996             !entity.hasInterestingTags();
68997     }
68998
68999
69000     var action = function(graph) {
69001         var relation = graph.entity(relationId);
69002
69003         graph.parentRelations(relation)
69004             .forEach(function(parent) {
69005                 parent = parent.removeMembersWithID(relationId);
69006                 graph = graph.replace(parent);
69007
69008                 if (parent.isDegenerate()) {
69009                     graph = actionDeleteRelation(parent.id)(graph);
69010                 }
69011             });
69012
69013         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
69014             graph = graph.replace(relation.removeMembersWithID(memberId));
69015
69016             var entity = graph.entity(memberId);
69017             if (canDeleteEntity(entity, graph)) {
69018                 graph = actionDeleteMultiple([memberId])(graph);
69019             }
69020         });
69021
69022         return graph.remove(relation);
69023     };
69024
69025
69026     return action;
69027 }
69028
69029 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
69030 function actionDeleteNode(nodeId) {
69031     var action = function(graph) {
69032         var node = graph.entity(nodeId);
69033
69034         graph.parentWays(node)
69035             .forEach(function(parent) {
69036                 parent = parent.removeNode(nodeId);
69037                 graph = graph.replace(parent);
69038
69039                 if (parent.isDegenerate()) {
69040                     graph = actionDeleteWay(parent.id)(graph);
69041                 }
69042             });
69043
69044         graph.parentRelations(node)
69045             .forEach(function(parent) {
69046                 parent = parent.removeMembersWithID(nodeId);
69047                 graph = graph.replace(parent);
69048
69049                 if (parent.isDegenerate()) {
69050                     graph = actionDeleteRelation(parent.id)(graph);
69051                 }
69052             });
69053
69054         return graph.remove(node);
69055     };
69056
69057
69058     return action;
69059 }
69060
69061 // Connect the ways at the given nodes.
69062 //
69063 // The last node will survive. All other nodes will be replaced with
69064 // the surviving node in parent ways, and then removed.
69065 //
69066 // Tags and relation memberships of of non-surviving nodes are merged
69067 // to the survivor.
69068 //
69069 // This is the inverse of `iD.actionDisconnect`.
69070 //
69071 // Reference:
69072 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
69073 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
69074 //
69075 function actionConnect(nodeIds) {
69076     return function(graph) {
69077         var survivor = graph.entity(lodash.last(nodeIds));
69078
69079         for (var i = 0; i < nodeIds.length - 1; i++) {
69080             var node = graph.entity(nodeIds[i]);
69081
69082             /* eslint-disable no-loop-func */
69083             graph.parentWays(node).forEach(function(parent) {
69084                 if (!parent.areAdjacent(node.id, survivor.id)) {
69085                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
69086                 }
69087             });
69088
69089             graph.parentRelations(node).forEach(function(parent) {
69090                 graph = graph.replace(parent.replaceMember(node, survivor));
69091             });
69092             /* eslint-enable no-loop-func */
69093
69094             survivor = survivor.mergeTags(node.tags);
69095             graph = actionDeleteNode(node.id)(graph);
69096         }
69097
69098         graph = graph.replace(survivor);
69099
69100         return graph;
69101     };
69102 }
69103
69104 function actionCopyEntities(ids, fromGraph) {
69105     var copies = {};
69106
69107
69108     var action = function(graph) {
69109         ids.forEach(function(id) {
69110             fromGraph.entity(id).copy(fromGraph, copies);
69111         });
69112
69113         for (var id in copies) {
69114             graph = graph.replace(copies[id]);
69115         }
69116
69117         return graph;
69118     };
69119
69120
69121     action.copies = function() {
69122         return copies;
69123     };
69124
69125
69126     return action;
69127 }
69128
69129 function actionDeleteMember(relationId, memberIndex) {
69130     return function(graph) {
69131         var relation = graph.entity(relationId)
69132             .removeMember(memberIndex);
69133
69134         graph = graph.replace(relation);
69135
69136         if (relation.isDegenerate())
69137             graph = actionDeleteRelation(relation.id)(graph);
69138
69139         return graph;
69140     };
69141 }
69142
69143 function actionDeprecateTags(entityId) {
69144
69145     return function(graph) {
69146         var entity = graph.entity(entityId),
69147             newtags = lodash.clone(entity.tags),
69148             change = false,
69149             rule;
69150
69151         // This handles dataDeprecated tags with a single condition
69152         for (var i = 0; i < dataDeprecated.length; i++) {
69153
69154             rule = dataDeprecated[i];
69155             var match = lodash.toPairs(rule.old)[0],
69156                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
69157
69158             if (entity.tags[match[0]] && match[1] === '*') {
69159
69160                 var value = entity.tags[match[0]];
69161                 if (replacements && !newtags[replacements[0][0]]) {
69162                     newtags[replacements[0][0]] = value;
69163                 }
69164                 delete newtags[match[0]];
69165                 change = true;
69166
69167             } else if (entity.tags[match[0]] === match[1]) {
69168                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
69169                 change = true;
69170             }
69171         }
69172
69173         if (change) {
69174             return graph.replace(entity.update({tags: newtags}));
69175         } else {
69176             return graph;
69177         }
69178     };
69179 }
69180
69181 function actionDiscardTags(difference) {
69182
69183     return function(graph) {
69184         function discardTags(entity) {
69185             if (!lodash.isEmpty(entity.tags)) {
69186                 var tags = {};
69187                 lodash.each(entity.tags, function(v, k) {
69188                     if (v) tags[k] = v;
69189                 });
69190
69191                 graph = graph.replace(entity.update({
69192                     tags: lodash.omit(tags, dataDiscarded)
69193                 }));
69194             }
69195         }
69196
69197         difference.modified().forEach(discardTags);
69198         difference.created().forEach(discardTags);
69199
69200         return graph;
69201     };
69202 }
69203
69204 // Disconect the ways at the given node.
69205 //
69206 // Optionally, disconnect only the given ways.
69207 //
69208 // For testing convenience, accepts an ID to assign to the (first) new node.
69209 // Normally, this will be undefined and the way will automatically
69210 // be assigned a new ID.
69211 //
69212 // This is the inverse of `iD.actionConnect`.
69213 //
69214 // Reference:
69215 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
69216 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
69217 //
69218 function actionDisconnect(nodeId, newNodeId) {
69219     var wayIds;
69220
69221
69222     var action = function(graph) {
69223         var node = graph.entity(nodeId),
69224             connections = action.connections(graph);
69225
69226         connections.forEach(function(connection) {
69227             var way = graph.entity(connection.wayID),
69228                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
69229
69230             graph = graph.replace(newNode);
69231             if (connection.index === 0 && way.isArea()) {
69232                 // replace shared node with shared node..
69233                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
69234             } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
69235                 // replace closing node with new new node..
69236                 graph = graph.replace(way.unclose().addNode(newNode.id));
69237             } else {
69238                 // replace shared node with multiple new nodes..
69239                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
69240             }
69241         });
69242
69243         return graph;
69244     };
69245
69246
69247     action.connections = function(graph) {
69248         var candidates = [],
69249             keeping = false,
69250             parentWays = graph.parentWays(graph.entity(nodeId));
69251
69252         parentWays.forEach(function(way) {
69253             if (wayIds && wayIds.indexOf(way.id) === -1) {
69254                 keeping = true;
69255                 return;
69256             }
69257             if (way.isArea() && (way.nodes[0] === nodeId)) {
69258                 candidates.push({ wayID: way.id, index: 0 });
69259             } else {
69260                 way.nodes.forEach(function(waynode, index) {
69261                     if (waynode === nodeId) {
69262                         candidates.push({ wayID: way.id, index: index });
69263                     }
69264                 });
69265             }
69266         });
69267
69268         return keeping ? candidates : candidates.slice(1);
69269     };
69270
69271
69272     action.disabled = function(graph) {
69273         var connections = action.connections(graph);
69274         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
69275             return 'not_connected';
69276
69277         var parentWays = graph.parentWays(graph.entity(nodeId)),
69278             seenRelationIds = {},
69279             sharedRelation;
69280
69281         parentWays.forEach(function(way) {
69282             if (wayIds && wayIds.indexOf(way.id) === -1)
69283                 return;
69284
69285             var relations = graph.parentRelations(way);
69286             relations.forEach(function(relation) {
69287                 if (relation.id in seenRelationIds) {
69288                     sharedRelation = relation;
69289                 } else {
69290                     seenRelationIds[relation.id] = true;
69291                 }
69292             });
69293         });
69294
69295         if (sharedRelation)
69296             return 'relation';
69297     };
69298
69299
69300     action.limitWays = function(_) {
69301         if (!arguments.length) return wayIds;
69302         wayIds = _;
69303         return action;
69304     };
69305
69306
69307     return action;
69308 }
69309
69310 // Join ways at the end node they share.
69311 //
69312 // This is the inverse of `iD.actionSplit`.
69313 //
69314 // Reference:
69315 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
69316 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
69317 //
69318 function actionJoin(ids) {
69319
69320     function groupEntitiesByGeometry(graph) {
69321         var entities = ids.map(function(id) { return graph.entity(id); });
69322         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69323     }
69324
69325
69326     var action = function(graph) {
69327         var ways = ids.map(graph.entity, graph),
69328             survivor = ways[0];
69329
69330         // Prefer to keep an existing way.
69331         for (var i = 0; i < ways.length; i++) {
69332             if (!ways[i].isNew()) {
69333                 survivor = ways[i];
69334                 break;
69335             }
69336         }
69337
69338         var joined = osmJoinWays(ways, graph)[0];
69339
69340         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
69341         graph = graph.replace(survivor);
69342
69343         joined.forEach(function(way) {
69344             if (way.id === survivor.id)
69345                 return;
69346
69347             graph.parentRelations(way).forEach(function(parent) {
69348                 graph = graph.replace(parent.replaceMember(way, survivor));
69349             });
69350
69351             survivor = survivor.mergeTags(way.tags);
69352
69353             graph = graph.replace(survivor);
69354             graph = actionDeleteWay(way.id)(graph);
69355         });
69356
69357         return graph;
69358     };
69359
69360
69361     action.disabled = function(graph) {
69362         var geometries = groupEntitiesByGeometry(graph);
69363         if (ids.length < 2 || ids.length !== geometries.line.length)
69364             return 'not_eligible';
69365
69366         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
69367         if (joined.length > 1)
69368             return 'not_adjacent';
69369
69370         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
69371             relation,
69372             tags = {},
69373             conflicting = false;
69374
69375         joined[0].forEach(function(way) {
69376             var parents = graph.parentRelations(way);
69377             parents.forEach(function(parent) {
69378                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
69379                     relation = parent;
69380             });
69381
69382             for (var k in way.tags) {
69383                 if (!(k in tags)) {
69384                     tags[k] = way.tags[k];
69385                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
69386                     conflicting = true;
69387                 }
69388             }
69389         });
69390
69391         if (relation)
69392             return 'restriction';
69393
69394         if (conflicting)
69395             return 'conflicting_tags';
69396     };
69397
69398
69399     return action;
69400 }
69401
69402 function actionMerge(ids) {
69403
69404     function groupEntitiesByGeometry(graph) {
69405         var entities = ids.map(function(id) { return graph.entity(id); });
69406         return lodash.extend({point: [], area: [], line: [], relation: []},
69407             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69408     }
69409
69410
69411     var action = function(graph) {
69412         var geometries = groupEntitiesByGeometry(graph),
69413             target = geometries.area[0] || geometries.line[0],
69414             points = geometries.point;
69415
69416         points.forEach(function(point) {
69417             target = target.mergeTags(point.tags);
69418             graph = graph.replace(target);
69419
69420             graph.parentRelations(point).forEach(function(parent) {
69421                 graph = graph.replace(parent.replaceMember(point, target));
69422             });
69423
69424             var nodes = lodash.uniq(graph.childNodes(target)),
69425                 removeNode = point;
69426
69427             for (var i = 0; i < nodes.length; i++) {
69428                 var node = nodes[i];
69429                 if (graph.parentWays(node).length > 1 ||
69430                     graph.parentRelations(node).length ||
69431                     node.hasInterestingTags()) {
69432                     continue;
69433                 }
69434
69435                 // Found an uninteresting child node on the target way.
69436                 // Move orig point into its place to preserve point's history. #3683
69437                 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
69438                 target = target.replaceNode(node.id, point.id);
69439                 graph = graph.replace(target);
69440                 removeNode = node;
69441                 break;
69442             }
69443
69444             graph = graph.remove(removeNode);
69445         });
69446
69447         return graph;
69448     };
69449
69450
69451     action.disabled = function(graph) {
69452         var geometries = groupEntitiesByGeometry(graph);
69453         if (geometries.point.length === 0 ||
69454             (geometries.area.length + geometries.line.length) !== 1 ||
69455             geometries.relation.length !== 0)
69456             return 'not_eligible';
69457     };
69458
69459
69460     return action;
69461 }
69462
69463 function actionMergePolygon(ids, newRelationId) {
69464
69465     function groupEntities(graph) {
69466         var entities = ids.map(function (id) { return graph.entity(id); });
69467         return lodash.extend({
69468                 closedWay: [],
69469                 multipolygon: [],
69470                 other: []
69471             }, lodash.groupBy(entities, function(entity) {
69472                 if (entity.type === 'way' && entity.isClosed()) {
69473                     return 'closedWay';
69474                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
69475                     return 'multipolygon';
69476                 } else {
69477                     return 'other';
69478                 }
69479             }));
69480     }
69481
69482
69483     var action = function(graph) {
69484         var entities = groupEntities(graph);
69485
69486         // An array representing all the polygons that are part of the multipolygon.
69487         //
69488         // Each element is itself an array of objects with an id property, and has a
69489         // locs property which is an array of the locations forming the polygon.
69490         var polygons = entities.multipolygon.reduce(function(polygons, m) {
69491             return polygons.concat(osmJoinWays(m.members, graph));
69492         }, []).concat(entities.closedWay.map(function(d) {
69493             var member = [{id: d.id}];
69494             member.nodes = graph.childNodes(d);
69495             return member;
69496         }));
69497
69498         // contained is an array of arrays of boolean values,
69499         // where contained[j][k] is true iff the jth way is
69500         // contained by the kth way.
69501         var contained = polygons.map(function(w, i) {
69502             return polygons.map(function(d, n) {
69503                 if (i === n) return null;
69504                 return geoPolygonContainsPolygon(
69505                     lodash.map(d.nodes, 'loc'),
69506                     lodash.map(w.nodes, 'loc'));
69507             });
69508         });
69509
69510         // Sort all polygons as either outer or inner ways
69511         var members = [],
69512             outer = true;
69513
69514         while (polygons.length) {
69515             extractUncontained(polygons);
69516             polygons = polygons.filter(isContained);
69517             contained = contained.filter(isContained).map(filterContained);
69518         }
69519
69520         function isContained(d, i) {
69521             return lodash.some(contained[i]);
69522         }
69523
69524         function filterContained(d) {
69525             return d.filter(isContained);
69526         }
69527
69528         function extractUncontained(polygons) {
69529             polygons.forEach(function(d, i) {
69530                 if (!isContained(d, i)) {
69531                     d.forEach(function(member) {
69532                         members.push({
69533                             type: 'way',
69534                             id: member.id,
69535                             role: outer ? 'outer' : 'inner'
69536                         });
69537                     });
69538                 }
69539             });
69540             outer = !outer;
69541         }
69542
69543         // Move all tags to one relation
69544         var relation = entities.multipolygon[0] ||
69545             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
69546
69547         entities.multipolygon.slice(1).forEach(function(m) {
69548             relation = relation.mergeTags(m.tags);
69549             graph = graph.remove(m);
69550         });
69551
69552         entities.closedWay.forEach(function(way) {
69553             function isThisOuter(m) {
69554                 return m.id === way.id && m.role !== 'inner';
69555             }
69556             if (members.some(isThisOuter)) {
69557                 relation = relation.mergeTags(way.tags);
69558                 graph = graph.replace(way.update({ tags: {} }));
69559             }
69560         });
69561
69562         return graph.replace(relation.update({
69563             members: members,
69564             tags: lodash.omit(relation.tags, 'area')
69565         }));
69566     };
69567
69568
69569     action.disabled = function(graph) {
69570         var entities = groupEntities(graph);
69571         if (entities.other.length > 0 ||
69572             entities.closedWay.length + entities.multipolygon.length < 2)
69573             return 'not_eligible';
69574         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
69575             return 'incomplete_relation';
69576     };
69577
69578
69579     return action;
69580 }
69581
69582 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
69583 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
69584 //
69585 // Permission is hereby granted, free of charge, to any person
69586 // obtaining a copy of this software and associated documentation files
69587 // (the "Software"), to deal in the Software without restriction,
69588 // including without limitation the rights to use, copy, modify, merge,
69589 // publish, distribute, sublicense, and/or sell copies of the Software,
69590 // and to permit persons to whom the Software is furnished to do so,
69591 // subject to the following conditions:
69592 //
69593 // The above copyright notice and this permission notice shall be
69594 // included in all copies or substantial portions of the Software.
69595 //
69596 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
69597 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69598 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69599 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
69600 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
69601 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
69602 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69603 // SOFTWARE.
69604
69605 // source:  https://bitbucket.org/lshift/synchrotron/src
69606 function longest_common_subsequence(file1, file2) {
69607     /* Text diff algorithm following Hunt and McIlroy 1976.
69608      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
69609      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
69610      * http://www.cs.dartmouth.edu/~doug/
69611      *
69612      * Expects two arrays of strings.
69613      */
69614     var equivalenceClasses;
69615     var file2indices;
69616     var newCandidate;
69617     var candidates;
69618     var line;
69619     var c, i, j, jX, r, s;
69620
69621     equivalenceClasses = {};
69622     for (j = 0; j < file2.length; j++) {
69623         line = file2[j];
69624         if (equivalenceClasses[line]) {
69625             equivalenceClasses[line].push(j);
69626         } else {
69627             equivalenceClasses[line] = [j];
69628         }
69629     }
69630
69631     candidates = [{file1index: -1,
69632                    file2index: -1,
69633                    chain: null}];
69634
69635     for (i = 0; i < file1.length; i++) {
69636         line = file1[i];
69637         file2indices = equivalenceClasses[line] || [];
69638
69639         r = 0;
69640         c = candidates[0];
69641
69642         for (jX = 0; jX < file2indices.length; jX++) {
69643             j = file2indices[jX];
69644
69645             for (s = 0; s < candidates.length; s++) {
69646                 if ((candidates[s].file2index < j) &&
69647                     ((s === candidates.length - 1) ||
69648                      (candidates[s + 1].file2index > j)))
69649                     break;
69650             }
69651
69652             if (s < candidates.length) {
69653                 newCandidate = {file1index: i,
69654                                 file2index: j,
69655                                 chain: candidates[s]};
69656                 if (r === candidates.length) {
69657                     candidates.push(c);
69658                 } else {
69659                     candidates[r] = c;
69660                 }
69661                 r = s + 1;
69662                 c = newCandidate;
69663                 if (r === candidates.length) {
69664                     break; // no point in examining further (j)s
69665                 }
69666             }
69667         }
69668
69669         candidates[r] = c;
69670     }
69671
69672     // At this point, we know the LCS: it's in the reverse of the
69673     // linked-list through .chain of
69674     // candidates[candidates.length - 1].
69675
69676     return candidates[candidates.length - 1];
69677 }
69678
69679
69680
69681
69682
69683
69684
69685
69686
69687
69688
69689 function diff_indices(file1, file2) {
69690     // We apply the LCS to give a simple representation of the
69691     // offsets and lengths of mismatched chunks in the input
69692     // files. This is used by diff3_merge_indices below.
69693
69694     var result = [];
69695     var tail1 = file1.length;
69696     var tail2 = file2.length;
69697
69698     for (var candidate = longest_common_subsequence(file1, file2);
69699          candidate !== null;
69700          candidate = candidate.chain)
69701     {
69702         var mismatchLength1 = tail1 - candidate.file1index - 1;
69703         var mismatchLength2 = tail2 - candidate.file2index - 1;
69704         tail1 = candidate.file1index;
69705         tail2 = candidate.file2index;
69706
69707         if (mismatchLength1 || mismatchLength2) {
69708             result.push({file1: [tail1 + 1, mismatchLength1],
69709                          file2: [tail2 + 1, mismatchLength2]});
69710         }
69711     }
69712
69713     result.reverse();
69714     return result;
69715 }
69716
69717 function diff3_merge_indices (a, o, b) {
69718     // Given three files, A, O, and B, where both A and B are
69719     // independently derived from O, returns a fairly complicated
69720     // internal representation of merge decisions it's taken. The
69721     // interested reader may wish to consult
69722     //
69723     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
69724     // Formal Investigation of Diff3." In Arvind and Prasad,
69725     // editors, Foundations of Software Technology and Theoretical
69726     // Computer Science (FSTTCS), December 2007.
69727     //
69728     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
69729     var i;
69730
69731     var m1 = diff_indices(o, a);
69732     var m2 = diff_indices(o, b);
69733
69734     var hunks = [];
69735     function addHunk(h, side) {
69736         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
69737     }
69738     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
69739     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
69740     hunks.sort();
69741
69742     var result = [];
69743     var commonOffset = 0;
69744     function copyCommon(targetOffset) {
69745         if (targetOffset > commonOffset) {
69746             result.push([1, commonOffset, targetOffset - commonOffset]);
69747             commonOffset = targetOffset;
69748         }
69749     }
69750
69751     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
69752         var firstHunkIndex = hunkIndex;
69753         var hunk = hunks[hunkIndex];
69754         var regionLhs = hunk[0];
69755         var regionRhs = regionLhs + hunk[2];
69756         while (hunkIndex < hunks.length - 1) {
69757             var maybeOverlapping = hunks[hunkIndex + 1];
69758             var maybeLhs = maybeOverlapping[0];
69759             if (maybeLhs > regionRhs) break;
69760             regionRhs = maybeLhs + maybeOverlapping[2];
69761             hunkIndex++;
69762         }
69763
69764         copyCommon(regionLhs);
69765         if (firstHunkIndex === hunkIndex) {
69766     // The "overlap" was only one hunk long, meaning that
69767     // there's no conflict here. Either a and o were the
69768     // same, or b and o were the same.
69769             if (hunk[4] > 0) {
69770                 result.push([hunk[1], hunk[3], hunk[4]]);
69771             }
69772         } else {
69773     // A proper conflict. Determine the extents of the
69774     // regions involved from a, o and b. Effectively merge
69775     // all the hunks on the left into one giant hunk, and
69776     // do the same for the right; then, correct for skew
69777     // in the regions of o that each side changed, and
69778     // report appropriate spans for the three sides.
69779     var regions = {
69780         0: [a.length, -1, o.length, -1],
69781         2: [b.length, -1, o.length, -1]
69782     };
69783             for (i = firstHunkIndex; i <= hunkIndex; i++) {
69784         hunk = hunks[i];
69785                 var side = hunk[1];
69786         var r = regions[side];
69787         var oLhs = hunk[0];
69788         var oRhs = oLhs + hunk[2];
69789                 var abLhs = hunk[3];
69790                 var abRhs = abLhs + hunk[4];
69791         r[0] = Math.min(abLhs, r[0]);
69792         r[1] = Math.max(abRhs, r[1]);
69793         r[2] = Math.min(oLhs, r[2]);
69794         r[3] = Math.max(oRhs, r[3]);
69795             }
69796     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
69797     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
69798     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
69799     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
69800             result.push([-1,
69801              aLhs,      aRhs      - aLhs,
69802              regionLhs, regionRhs - regionLhs,
69803              bLhs,      bRhs      - bLhs]);
69804         }
69805         commonOffset = regionRhs;
69806     }
69807
69808     copyCommon(o.length);
69809     return result;
69810 }
69811
69812 function diff3_merge (a, o, b, excludeFalseConflicts) {
69813     // Applies the output of Diff3.diff3_merge_indices to actually
69814     // construct the merged file; the returned result alternates
69815     // between "ok" and "conflict" blocks.
69816
69817     var result = [];
69818     var files = [a, o, b];
69819     var indices = diff3_merge_indices(a, o, b);
69820
69821     var okLines = [];
69822     function flushOk() {
69823         if (okLines.length) {
69824             result.push({ok: okLines});
69825         }
69826         okLines = [];
69827     }
69828     function pushOk(xs) {
69829         for (var j = 0; j < xs.length; j++) {
69830             okLines.push(xs[j]);
69831         }
69832     }
69833
69834     function isTrueConflict(rec) {
69835         if (rec[2] !== rec[6]) return true;
69836         var aoff = rec[1];
69837         var boff = rec[5];
69838         for (var j = 0; j < rec[2]; j++) {
69839             if (a[j + aoff] !== b[j + boff]) return true;
69840         }
69841         return false;
69842     }
69843
69844     for (var i = 0; i < indices.length; i++) {
69845         var x = indices[i];
69846         var side = x[0];
69847         if (side === -1) {
69848             if (excludeFalseConflicts && !isTrueConflict(x)) {
69849                 pushOk(files[0].slice(x[1], x[1] + x[2]));
69850             } else {
69851                 flushOk();
69852                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
69853                                         aIndex: x[1],
69854                                         o: o.slice(x[3], x[3] + x[4]),
69855                                         oIndex: x[3],
69856                                         b: b.slice(x[5], x[5] + x[6]),
69857                                         bIndex: x[5]}});
69858             }
69859         } else {
69860             pushOk(files[side].slice(x[1], x[1] + x[2]));
69861         }
69862     }
69863
69864     flushOk();
69865     return result;
69866 }
69867
69868 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
69869     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
69870         conflicts = [];
69871
69872
69873     function user(d) {
69874         return lodash.isFunction(formatUser) ? formatUser(d) : d;
69875     }
69876
69877
69878     function mergeLocation(remote, target) {
69879         function pointEqual(a, b) {
69880             var epsilon = 1e-6;
69881             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
69882         }
69883
69884         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
69885             return target;
69886         }
69887         if (option === 'force_remote') {
69888             return target.update({loc: remote.loc});
69889         }
69890
69891         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
69892         return target;
69893     }
69894
69895
69896     function mergeNodes(base, remote, target) {
69897         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
69898             return target;
69899         }
69900         if (option === 'force_remote') {
69901             return target.update({nodes: remote.nodes});
69902         }
69903
69904         var ccount = conflicts.length,
69905             o = base.nodes || [],
69906             a = target.nodes || [],
69907             b = remote.nodes || [],
69908             nodes = [],
69909             hunks = diff3_merge(a, o, b, true);
69910
69911         for (var i = 0; i < hunks.length; i++) {
69912             var hunk = hunks[i];
69913             if (hunk.ok) {
69914                 nodes.push.apply(nodes, hunk.ok);
69915             } else {
69916                 // for all conflicts, we can assume c.a !== c.b
69917                 // because `diff3_merge` called with `true` option to exclude false conflicts..
69918                 var c = hunk.conflict;
69919                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
69920                     nodes.push.apply(nodes, c.b);
69921                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
69922                     nodes.push.apply(nodes, c.a);
69923                 } else {       // changed both locally and remotely
69924                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
69925                     break;
69926                 }
69927             }
69928         }
69929
69930         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
69931     }
69932
69933
69934     function mergeChildren(targetWay, children, updates, graph) {
69935         function isUsed(node, targetWay) {
69936             var parentWays = lodash.map(graph.parentWays(node), 'id');
69937             return node.hasInterestingTags() ||
69938                 lodash.without(parentWays, targetWay.id).length > 0 ||
69939                 graph.parentRelations(node).length > 0;
69940         }
69941
69942         var ccount = conflicts.length;
69943
69944         for (var i = 0; i < children.length; i++) {
69945             var id = children[i],
69946                 node = graph.hasEntity(id);
69947
69948             // remove unused childNodes..
69949             if (targetWay.nodes.indexOf(id) === -1) {
69950                 if (node && !isUsed(node, targetWay)) {
69951                     updates.removeIds.push(id);
69952                 }
69953                 continue;
69954             }
69955
69956             // restore used childNodes..
69957             var local = localGraph.hasEntity(id),
69958                 remote = remoteGraph.hasEntity(id),
69959                 target;
69960
69961             if (option === 'force_remote' && remote && remote.visible) {
69962                 updates.replacements.push(remote);
69963
69964             } else if (option === 'force_local' && local) {
69965                 target = osmEntity$$1(local);
69966                 if (remote) {
69967                     target = target.update({ version: remote.version });
69968                 }
69969                 updates.replacements.push(target);
69970
69971             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
69972                 target = osmEntity$$1(local, { version: remote.version });
69973                 if (remote.visible) {
69974                     target = mergeLocation(remote, target);
69975                 } else {
69976                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
69977                 }
69978
69979                 if (conflicts.length !== ccount) break;
69980                 updates.replacements.push(target);
69981             }
69982         }
69983
69984         return targetWay;
69985     }
69986
69987
69988     function updateChildren(updates, graph) {
69989         for (var i = 0; i < updates.replacements.length; i++) {
69990             graph = graph.replace(updates.replacements[i]);
69991         }
69992         if (updates.removeIds.length) {
69993             graph = actionDeleteMultiple(updates.removeIds)(graph);
69994         }
69995         return graph;
69996     }
69997
69998
69999     function mergeMembers(remote, target) {
70000         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
70001             return target;
70002         }
70003         if (option === 'force_remote') {
70004             return target.update({members: remote.members});
70005         }
70006
70007         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
70008         return target;
70009     }
70010
70011
70012     function mergeTags(base, remote, target) {
70013         function ignoreKey(k) {
70014             return lodash.includes(dataDiscarded, k);
70015         }
70016
70017         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
70018             return target;
70019         }
70020         if (option === 'force_remote') {
70021             return target.update({tags: remote.tags});
70022         }
70023
70024         var ccount = conflicts.length,
70025             o = base.tags || {},
70026             a = target.tags || {},
70027             b = remote.tags || {},
70028             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
70029             tags = lodash.clone(a),
70030             changed = false;
70031
70032         for (var i = 0; i < keys.length; i++) {
70033             var k = keys[i];
70034
70035             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
70036                 if (o[k] !== a[k]) {      // changed locally..
70037                     conflicts.push(t('merge_remote_changes.conflict.tags',
70038                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
70039
70040                 } else {                  // unchanged locally, accept remote change..
70041                     if (b.hasOwnProperty(k)) {
70042                         tags[k] = b[k];
70043                     } else {
70044                         delete tags[k];
70045                     }
70046                     changed = true;
70047                 }
70048             }
70049         }
70050
70051         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
70052     }
70053
70054
70055     //  `graph.base()` is the common ancestor of the two graphs.
70056     //  `localGraph` contains user's edits up to saving
70057     //  `remoteGraph` contains remote edits to modified nodes
70058     //  `graph` must be a descendent of `localGraph` and may include
70059     //      some conflict resolution actions performed on it.
70060     //
70061     //                  --- ... --- `localGraph` -- ... -- `graph`
70062     //                 /
70063     //  `graph.base()` --- ... --- `remoteGraph`
70064     //
70065     var action = function(graph) {
70066         var updates = { replacements: [], removeIds: [] },
70067             base = graph.base().entities[id],
70068             local = localGraph.entity(id),
70069             remote = remoteGraph.entity(id),
70070             target = osmEntity$$1(local, { version: remote.version });
70071
70072         // delete/undelete
70073         if (!remote.visible) {
70074             if (option === 'force_remote') {
70075                 return actionDeleteMultiple([id])(graph);
70076
70077             } else if (option === 'force_local') {
70078                 if (target.type === 'way') {
70079                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
70080                     graph = updateChildren(updates, graph);
70081                 }
70082                 return graph.replace(target);
70083
70084             } else {
70085                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
70086                 return graph;  // do nothing
70087             }
70088         }
70089
70090         // merge
70091         if (target.type === 'node') {
70092             target = mergeLocation(remote, target);
70093
70094         } else if (target.type === 'way') {
70095             // pull in any child nodes that may not be present locally..
70096             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
70097             target = mergeNodes(base, remote, target);
70098             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
70099
70100         } else if (target.type === 'relation') {
70101             target = mergeMembers(remote, target);
70102         }
70103
70104         target = mergeTags(base, remote, target);
70105
70106         if (!conflicts.length) {
70107             graph = updateChildren(updates, graph).replace(target);
70108         }
70109
70110         return graph;
70111     };
70112
70113
70114     action.withOption = function(opt) {
70115         option = opt;
70116         return action;
70117     };
70118
70119
70120     action.conflicts = function() {
70121         return conflicts;
70122     };
70123
70124
70125     return action;
70126 }
70127
70128 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70129 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70130 function actionMove(moveIds, tryDelta, projection, cache) {
70131     var delta = tryDelta;
70132
70133     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
70134     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
70135
70136     function setupCache(graph) {
70137         function canMove(nodeId) {
70138             // Allow movement of any node that is in the selectedIDs list..
70139             if (moveIds.indexOf(nodeId) !== -1) return true;
70140
70141             // Allow movement of a vertex where 2 ways meet..
70142             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
70143             if (parents.length < 3) return true;
70144
70145             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
70146             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
70147             if (!parentsMoving) delete cache.moving[nodeId];
70148
70149             return parentsMoving;
70150         }
70151
70152         function cacheEntities(ids) {
70153             ids.forEach(function(id) {
70154                 if (cache.moving[id]) return;
70155                 cache.moving[id] = true;
70156
70157                 var entity = graph.hasEntity(id);
70158                 if (!entity) return;
70159
70160                 if (entity.type === 'node') {
70161                     cache.nodes.push(id);
70162                     cache.startLoc[id] = entity.loc;
70163                 } else if (entity.type === 'way') {
70164                     cache.ways.push(id);
70165                     cacheEntities(entity.nodes);
70166                 } else {
70167                     cacheEntities(entity.members.map(function(member) {
70168                         return member.id;
70169                     }));
70170                 }
70171             });
70172         }
70173
70174         function cacheIntersections(ids) {
70175             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
70176
70177             ids.forEach(function(id) {
70178                 // consider only intersections with 1 moved and 1 unmoved way.
70179                 var childNodes = graph.childNodes(graph.entity(id));
70180                 childNodes.forEach(function(node) {
70181                     var parents = graph.parentWays(node);
70182                     if (parents.length !== 2) return;
70183
70184                     var moved = graph.entity(id),
70185                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
70186                     if (!unmoved) return;
70187
70188                     // exclude ways that are overly connected..
70189                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
70190
70191                     if (moved.isArea() || unmoved.isArea()) return;
70192
70193                     cache.intersection[node.id] = {
70194                         nodeId: node.id,
70195                         movedId: moved.id,
70196                         unmovedId: unmoved.id,
70197                         movedIsEP: isEndpoint(moved, node.id),
70198                         unmovedIsEP: isEndpoint(unmoved, node.id)
70199                     };
70200                 });
70201             });
70202         }
70203
70204
70205         if (!cache) {
70206             cache = {};
70207         }
70208         if (!cache.ok) {
70209             cache.moving = {};
70210             cache.intersection = {};
70211             cache.replacedVertex = {};
70212             cache.startLoc = {};
70213             cache.nodes = [];
70214             cache.ways = [];
70215
70216             cacheEntities(moveIds);
70217             cacheIntersections(cache.ways);
70218             cache.nodes = lodash.filter(cache.nodes, canMove);
70219
70220             cache.ok = true;
70221         }
70222     }
70223
70224
70225     // Place a vertex where the moved vertex used to be, to preserve way shape..
70226     function replaceMovedVertex(nodeId, wayId, graph, delta) {
70227         var way = graph.entity(wayId),
70228             moved = graph.entity(nodeId),
70229             movedIndex = way.nodes.indexOf(nodeId),
70230             len, prevIndex, nextIndex;
70231
70232         if (way.isClosed()) {
70233             len = way.nodes.length - 1;
70234             prevIndex = (movedIndex + len - 1) % len;
70235             nextIndex = (movedIndex + len + 1) % len;
70236         } else {
70237             len = way.nodes.length;
70238             prevIndex = movedIndex - 1;
70239             nextIndex = movedIndex + 1;
70240         }
70241
70242         var prev = graph.hasEntity(way.nodes[prevIndex]),
70243             next = graph.hasEntity(way.nodes[nextIndex]);
70244
70245         // Don't add orig vertex at endpoint..
70246         if (!prev || !next) return graph;
70247
70248         var key = wayId + '_' + nodeId,
70249             orig = cache.replacedVertex[key];
70250         if (!orig) {
70251             orig = osmNode();
70252             cache.replacedVertex[key] = orig;
70253             cache.startLoc[orig.id] = cache.startLoc[nodeId];
70254         }
70255
70256         var start, end;
70257         if (delta) {
70258             start = projection(cache.startLoc[nodeId]);
70259             end = projection.invert(vecAdd(start, delta));
70260         } else {
70261             end = cache.startLoc[nodeId];
70262         }
70263         orig = orig.move(end);
70264
70265         var angle = Math.abs(geoAngle(orig, prev, projection) -
70266                 geoAngle(orig, next, projection)) * 180 / Math.PI;
70267
70268         // Don't add orig vertex if it would just make a straight line..
70269         if (angle > 175 && angle < 185) return graph;
70270
70271         // Don't add orig vertex if another point is already nearby (within 10m)
70272         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
70273             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
70274
70275         // moving forward or backward along way?
70276         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
70277             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
70278             d1 = geoPathLength(p1),
70279             d2 = geoPathLength(p2),
70280             insertAt = (d1 < d2) ? movedIndex : nextIndex;
70281
70282         // moving around closed loop?
70283         if (way.isClosed() && insertAt === 0) insertAt = len;
70284
70285         way = way.addNode(orig.id, insertAt);
70286         return graph.replace(orig).replace(way);
70287     }
70288
70289
70290     // Reorder nodes around intersections that have moved..
70291     function unZorroIntersection(intersection, graph) {
70292         var vertex = graph.entity(intersection.nodeId),
70293             way1 = graph.entity(intersection.movedId),
70294             way2 = graph.entity(intersection.unmovedId),
70295             isEP1 = intersection.movedIsEP,
70296             isEP2 = intersection.unmovedIsEP;
70297
70298         // don't move the vertex if it is the endpoint of both ways.
70299         if (isEP1 && isEP2) return graph;
70300
70301         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
70302             nodes2 = lodash.without(graph.childNodes(way2), vertex);
70303
70304         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
70305         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
70306
70307         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
70308             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
70309             loc;
70310
70311         // snap vertex to nearest edge (or some point between them)..
70312         if (!isEP1 && !isEP2) {
70313             var epsilon = 1e-4, maxIter = 10;
70314             for (var i = 0; i < maxIter; i++) {
70315                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
70316                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
70317                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
70318                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
70319             }
70320         } else if (!isEP1) {
70321             loc = edge1.loc;
70322         } else {
70323             loc = edge2.loc;
70324         }
70325
70326         graph = graph.replace(vertex.move(loc));
70327
70328         // if zorro happened, reorder nodes..
70329         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
70330             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
70331             graph = graph.replace(way1);
70332         }
70333         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
70334             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
70335             graph = graph.replace(way2);
70336         }
70337
70338         return graph;
70339     }
70340
70341
70342     function cleanupIntersections(graph) {
70343         lodash.each(cache.intersection, function(obj) {
70344             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
70345             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
70346             graph = unZorroIntersection(obj, graph);
70347         });
70348
70349         return graph;
70350     }
70351
70352
70353     // check if moving way endpoint can cross an unmoved way, if so limit delta..
70354     function limitDelta(graph) {
70355         lodash.each(cache.intersection, function(obj) {
70356             // Don't limit movement if this is vertex joins 2 endpoints..
70357             if (obj.movedIsEP && obj.unmovedIsEP) return;
70358             // Don't limit movement if this vertex is not an endpoint anyway..
70359             if (!obj.movedIsEP) return;
70360
70361             var node = graph.entity(obj.nodeId),
70362                 start = projection(node.loc),
70363                 end = vecAdd(start, delta),
70364                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
70365                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
70366                     function(loc) { return vecAdd(projection(loc), delta); }),
70367                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
70368                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
70369                 hits = geoPathIntersections(movedPath, unmovedPath);
70370
70371             for (var i = 0; i < hits.length; i++) {
70372                 if (lodash.isEqual(hits[i], end)) continue;
70373                 var edge = geoChooseEdge(unmovedNodes, end, projection);
70374                 delta = vecSub(projection(edge.loc), start);
70375             }
70376         });
70377     }
70378
70379
70380     var action = function(graph) {
70381         if (delta[0] === 0 && delta[1] === 0) return graph;
70382
70383         setupCache(graph);
70384
70385         if (!lodash.isEmpty(cache.intersection)) {
70386             limitDelta(graph);
70387         }
70388
70389         lodash.each(cache.nodes, function(id) {
70390             var node = graph.entity(id),
70391                 start = projection(node.loc),
70392                 end = vecAdd(start, delta);
70393             graph = graph.replace(node.move(projection.invert(end)));
70394         });
70395
70396         if (!lodash.isEmpty(cache.intersection)) {
70397             graph = cleanupIntersections(graph);
70398         }
70399
70400         return graph;
70401     };
70402
70403
70404     action.delta = function() {
70405         return delta;
70406     };
70407
70408
70409     return action;
70410 }
70411
70412 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70413 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70414 function actionMoveNode(nodeId, loc) {
70415     return function(graph) {
70416         return graph.replace(graph.entity(nodeId).move(loc));
70417     };
70418 }
70419
70420 function actionNoop() {
70421     return function(graph) {
70422         return graph;
70423     };
70424 }
70425
70426 /*
70427  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
70428  */
70429 function actionOrthogonalize(wayId, projection) {
70430     var threshold = 12, // degrees within right or straight to alter
70431         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
70432         upperThreshold = Math.cos(threshold * Math.PI / 180);
70433
70434
70435     var action = function(graph, t) {
70436         if (t === null || !isFinite(t)) t = 1;
70437         t = Math.min(Math.max(+t, 0), 1);
70438
70439         var way = graph.entity(wayId),
70440             nodes = graph.childNodes(way),
70441             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
70442             corner = {i: 0, dotp: 1},
70443             epsilon = 1e-4,
70444             node, loc, score, motions, i, j;
70445
70446         if (points.length === 3) {   // move only one vertex for right triangle
70447             for (i = 0; i < 1000; i++) {
70448                 motions = points.map(calcMotion);
70449                 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
70450                 score = corner.dotp;
70451                 if (score < epsilon) {
70452                     break;
70453                 }
70454             }
70455
70456             node = graph.entity(nodes[corner.i].id);
70457             loc = projection.invert(points[corner.i]);
70458             graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70459
70460         } else {
70461             var best,
70462                 originalPoints = lodash.clone(points);
70463             score = Infinity;
70464
70465             for (i = 0; i < 1000; i++) {
70466                 motions = points.map(calcMotion);
70467                 for (j = 0; j < motions.length; j++) {
70468                     points[j] = addPoints(points[j],motions[j]);
70469                 }
70470                 var newScore = squareness(points);
70471                 if (newScore < score) {
70472                     best = lodash.clone(points);
70473                     score = newScore;
70474                 }
70475                 if (score < epsilon) {
70476                     break;
70477                 }
70478             }
70479
70480             points = best;
70481
70482             for (i = 0; i < points.length; i++) {
70483                 // only move the points that actually moved
70484                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
70485                     loc = projection.invert(points[i]);
70486                     node = graph.entity(nodes[i].id);
70487                     graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70488                 }
70489             }
70490
70491             // remove empty nodes on straight sections
70492             for (i = 0; t === 1 && i < points.length; i++) {
70493                 node = graph.entity(nodes[i].id);
70494
70495                 if (graph.parentWays(node).length > 1 ||
70496                     graph.parentRelations(node).length ||
70497                     node.hasInterestingTags()) {
70498                     continue;
70499                 }
70500
70501                 var dotp = normalizedDotProduct(i, points);
70502                 if (dotp < -1 + epsilon) {
70503                     graph = actionDeleteNode(node.id)(graph);
70504                 }
70505             }
70506         }
70507
70508         return graph;
70509
70510
70511         function calcMotion(b, i, array) {
70512             var a = array[(i - 1 + array.length) % array.length],
70513                 c = array[(i + 1) % array.length],
70514                 p = subtractPoints(a, b),
70515                 q = subtractPoints(c, b),
70516                 scale, dotp;
70517
70518             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
70519             p = normalizePoint(p, 1.0);
70520             q = normalizePoint(q, 1.0);
70521
70522             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
70523
70524             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
70525             if (array.length > 3) {
70526                 if (dotp < -0.707106781186547) {
70527                     dotp += 1.0;
70528                 }
70529             } else if (dotp && Math.abs(dotp) < corner.dotp) {
70530                 corner.i = i;
70531                 corner.dotp = Math.abs(dotp);
70532             }
70533
70534             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
70535         }
70536     };
70537
70538
70539     function squareness(points) {
70540         return points.reduce(function(sum, val, i, array) {
70541             var dotp = normalizedDotProduct(i, array);
70542
70543             dotp = filterDotProduct(dotp);
70544             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
70545         }, 0);
70546     }
70547
70548
70549     function normalizedDotProduct(i, points) {
70550         var a = points[(i - 1 + points.length) % points.length],
70551             b = points[i],
70552             c = points[(i + 1) % points.length],
70553             p = subtractPoints(a, b),
70554             q = subtractPoints(c, b);
70555
70556         p = normalizePoint(p, 1.0);
70557         q = normalizePoint(q, 1.0);
70558
70559         return p[0] * q[0] + p[1] * q[1];
70560     }
70561
70562
70563     function subtractPoints(a, b) {
70564         return [a[0] - b[0], a[1] - b[1]];
70565     }
70566
70567
70568     function addPoints(a, b) {
70569         return [a[0] + b[0], a[1] + b[1]];
70570     }
70571
70572
70573     function normalizePoint(point, scale) {
70574         var vector = [0, 0];
70575         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
70576         if (length !== 0) {
70577             vector[0] = point[0] / length;
70578             vector[1] = point[1] / length;
70579         }
70580
70581         vector[0] *= scale;
70582         vector[1] *= scale;
70583
70584         return vector;
70585     }
70586
70587
70588     function filterDotProduct(dotp) {
70589         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
70590             return dotp;
70591         }
70592
70593         return 0;
70594     }
70595
70596
70597     action.disabled = function(graph) {
70598         var way = graph.entity(wayId),
70599             nodes = graph.childNodes(way),
70600             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
70601
70602         if (squareness(points)) {
70603             return false;
70604         }
70605
70606         return 'not_squarish';
70607     };
70608
70609
70610     action.transitionable = true;
70611
70612
70613     return action;
70614 }
70615
70616 // Split a way at the given node.
70617 //
70618 // Optionally, split only the given ways, if multiple ways share
70619 // the given node.
70620 //
70621 // This is the inverse of `iD.actionJoin`.
70622 //
70623 // For testing convenience, accepts an ID to assign to the new way.
70624 // Normally, this will be undefined and the way will automatically
70625 // be assigned a new ID.
70626 //
70627 // Reference:
70628 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
70629 //
70630 function actionSplit(nodeId, newWayIds) {
70631     var wayIds;
70632
70633     // if the way is closed, we need to search for a partner node
70634     // to split the way at.
70635     //
70636     // The following looks for a node that is both far away from
70637     // the initial node in terms of way segment length and nearby
70638     // in terms of beeline-distance. This assures that areas get
70639     // split on the most "natural" points (independent of the number
70640     // of nodes).
70641     // For example: bone-shaped areas get split across their waist
70642     // line, circles across the diameter.
70643     function splitArea(nodes, idxA, graph) {
70644         var lengths = new Array(nodes.length),
70645             length,
70646             i,
70647             best = 0,
70648             idxB;
70649
70650         function wrap(index) {
70651             return utilWrap(index, nodes.length);
70652         }
70653
70654         function dist(nA, nB) {
70655             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
70656         }
70657
70658         // calculate lengths
70659         length = 0;
70660         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
70661             length += dist(nodes[i], nodes[wrap(i-1)]);
70662             lengths[i] = length;
70663         }
70664
70665         length = 0;
70666         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
70667             length += dist(nodes[i], nodes[wrap(i+1)]);
70668             if (length < lengths[i])
70669                 lengths[i] = length;
70670         }
70671
70672         // determine best opposite node to split
70673         for (i = 0; i < nodes.length; i++) {
70674             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
70675             if (cost > best) {
70676                 idxB = i;
70677                 best = cost;
70678             }
70679         }
70680
70681         return idxB;
70682     }
70683
70684
70685     function split(graph, wayA, newWayId) {
70686         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
70687             nodesA,
70688             nodesB,
70689             isArea = wayA.isArea(),
70690             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
70691
70692         if (wayA.isClosed()) {
70693             var nodes = wayA.nodes.slice(0, -1),
70694                 idxA = lodash.indexOf(nodes, nodeId),
70695                 idxB = splitArea(nodes, idxA, graph);
70696
70697             if (idxB < idxA) {
70698                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
70699                 nodesB = nodes.slice(idxB, idxA + 1);
70700             } else {
70701                 nodesA = nodes.slice(idxA, idxB + 1);
70702                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
70703             }
70704         } else {
70705             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
70706             nodesA = wayA.nodes.slice(0, idx + 1);
70707             nodesB = wayA.nodes.slice(idx);
70708         }
70709
70710         wayA = wayA.update({nodes: nodesA});
70711         wayB = wayB.update({nodes: nodesB});
70712
70713         graph = graph.replace(wayA);
70714         graph = graph.replace(wayB);
70715
70716         graph.parentRelations(wayA).forEach(function(relation) {
70717             if (relation.isRestriction()) {
70718                 var via = relation.memberByRole('via');
70719                 if (via && wayB.contains(via.id)) {
70720                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
70721                     graph = graph.replace(relation);
70722                 }
70723             } else {
70724                 if (relation === isOuter) {
70725                     graph = graph.replace(relation.mergeTags(wayA.tags));
70726                     graph = graph.replace(wayA.update({tags: {}}));
70727                     graph = graph.replace(wayB.update({tags: {}}));
70728                 }
70729
70730                 var member = {
70731                     id: wayB.id,
70732                     type: 'way',
70733                     role: relation.memberById(wayA.id).role
70734                 };
70735
70736                 graph = actionAddMember(relation.id, member)(graph);
70737             }
70738         });
70739
70740         if (!isOuter && isArea) {
70741             var multipolygon = osmRelation({
70742                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
70743                 members: [
70744                     {id: wayA.id, role: 'outer', type: 'way'},
70745                     {id: wayB.id, role: 'outer', type: 'way'}
70746                 ]});
70747
70748             graph = graph.replace(multipolygon);
70749             graph = graph.replace(wayA.update({tags: {}}));
70750             graph = graph.replace(wayB.update({tags: {}}));
70751         }
70752
70753         return graph;
70754     }
70755
70756
70757     var action = function(graph) {
70758         var candidates = action.ways(graph);
70759         for (var i = 0; i < candidates.length; i++) {
70760             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
70761         }
70762         return graph;
70763     };
70764
70765
70766     action.ways = function(graph) {
70767         var node = graph.entity(nodeId),
70768             parents = graph.parentWays(node),
70769             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
70770
70771         return parents.filter(function(parent) {
70772             if (wayIds && wayIds.indexOf(parent.id) === -1)
70773                 return false;
70774
70775             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
70776                 return false;
70777
70778             if (parent.isClosed()) {
70779                 return true;
70780             }
70781
70782             for (var i = 1; i < parent.nodes.length - 1; i++) {
70783                 if (parent.nodes[i] === nodeId) {
70784                     return true;
70785                 }
70786             }
70787
70788             return false;
70789         });
70790     };
70791
70792
70793     action.disabled = function(graph) {
70794         var candidates = action.ways(graph);
70795         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
70796             return 'not_eligible';
70797     };
70798
70799
70800     action.limitWays = function(_) {
70801         if (!arguments.length) return wayIds;
70802         wayIds = _;
70803         return action;
70804     };
70805
70806
70807     return action;
70808 }
70809
70810 // Create a restriction relation for `turn`, which must have the following structure:
70811 //
70812 //     {
70813 //         from: { node: <node ID>, way: <way ID> },
70814 //         via:  { node: <node ID> },
70815 //         to:   { node: <node ID>, way: <way ID> },
70816 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
70817 //     }
70818 //
70819 // This specifies a restriction of type `restriction` when traveling from
70820 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
70821 // (The action does not check that these entities form a valid intersection.)
70822 //
70823 // If `restriction` is not provided, it is automatically determined by
70824 // osmInferRestriction.
70825 //
70826 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
70827 // and `to.node` are used to determine which portion of the split ways become
70828 // members of the restriction.
70829 //
70830 // For testing convenience, accepts an ID to assign to the new relation.
70831 // Normally, this will be undefined and the relation will automatically
70832 // be assigned a new ID.
70833 //
70834 function actionRestrictTurn(turn, projection, restrictionId) {
70835
70836     return function(graph) {
70837         var from = graph.entity(turn.from.way),
70838             via  = graph.entity(turn.via.node),
70839             to   = graph.entity(turn.to.way);
70840
70841         function isClosingNode(way, nodeId) {
70842             return nodeId === way.first() && nodeId === way.last();
70843         }
70844
70845         function split(toOrFrom) {
70846             var newID = toOrFrom.newID || osmWay().id;
70847             graph = actionSplit(via.id, [newID])
70848                 .limitWays([toOrFrom.way])(graph);
70849
70850             var a = graph.entity(newID),
70851                 b = graph.entity(toOrFrom.way);
70852
70853             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
70854                 return [a, b];
70855             } else {
70856                 return [b, a];
70857             }
70858         }
70859
70860         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
70861             if (turn.from.node === turn.to.node) {
70862                 // U-turn
70863                 from = to = split(turn.from)[0];
70864             } else if (turn.from.way === turn.to.way) {
70865                 // Straight-on or circular
70866                 var s = split(turn.from);
70867                 from = s[0];
70868                 to   = s[1];
70869             } else {
70870                 // Other
70871                 from = split(turn.from)[0];
70872             }
70873         }
70874
70875         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
70876             to = split(turn.to)[0];
70877         }
70878
70879         return graph.replace(osmRelation({
70880             id: restrictionId,
70881             tags: {
70882                 type: 'restriction',
70883                 restriction: turn.restriction ||
70884                     osmInferRestriction(
70885                         graph,
70886                         turn.from,
70887                         turn.via,
70888                         turn.to,
70889                         projection)
70890             },
70891             members: [
70892                 {id: from.id, type: 'way',  role: 'from'},
70893                 {id: via.id,  type: 'node', role: 'via'},
70894                 {id: to.id,   type: 'way',  role: 'to'}
70895             ]
70896         }));
70897     };
70898 }
70899
70900 function actionRevert(id) {
70901     var action = function(graph) {
70902         var entity = graph.hasEntity(id),
70903             base = graph.base().entities[id];
70904
70905         if (entity && !base) {    // entity will be removed..
70906             if (entity.type === 'node') {
70907                 graph.parentWays(entity)
70908                     .forEach(function(parent) {
70909                         parent = parent.removeNode(id);
70910                         graph = graph.replace(parent);
70911
70912                         if (parent.isDegenerate()) {
70913                             graph = actionDeleteWay(parent.id)(graph);
70914                         }
70915                     });
70916             }
70917
70918             graph.parentRelations(entity)
70919                 .forEach(function(parent) {
70920                     parent = parent.removeMembersWithID(id);
70921                     graph = graph.replace(parent);
70922
70923                     if (parent.isDegenerate()) {
70924                         graph = actionDeleteRelation(parent.id)(graph);
70925                     }
70926                 });
70927         }
70928
70929         return graph.revert(id);
70930     };
70931
70932     return action;
70933 }
70934
70935 function actionRotate(rotateIds, pivot, angle, projection) {
70936
70937     var action = function(graph) {
70938         return graph.update(function(graph) {
70939             utilGetAllNodes(rotateIds, graph).forEach(function(node) {
70940                 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
70941                 graph = graph.replace(node.move(projection.invert(point)));
70942             });
70943         });
70944     };
70945
70946     return action;
70947 }
70948
70949 /*
70950  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
70951  */
70952 function actionStraighten(wayId, projection) {
70953
70954     function positionAlongWay(n, s, e) {
70955         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
70956                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
70957     }
70958
70959
70960     var action = function(graph, t) {
70961         if (t === null || !isFinite(t)) t = 1;
70962         t = Math.min(Math.max(+t, 0), 1);
70963
70964         var way = graph.entity(wayId),
70965             nodes = graph.childNodes(way),
70966             points = nodes.map(function(n) { return projection(n.loc); }),
70967             startPoint = points[0],
70968             endPoint = points[points.length-1],
70969             toDelete = [],
70970             i;
70971
70972         for (i = 1; i < points.length-1; i++) {
70973             var node = nodes[i],
70974                 point = points[i];
70975
70976             if (t < 1 || graph.parentWays(node).length > 1 ||
70977                 graph.parentRelations(node).length ||
70978                 node.hasInterestingTags()) {
70979
70980                 var u = positionAlongWay(point, startPoint, endPoint),
70981                     p = [
70982                         startPoint[0] + u * (endPoint[0] - startPoint[0]),
70983                         startPoint[1] + u * (endPoint[1] - startPoint[1])
70984                     ],
70985                     loc2 = projection.invert(p);
70986
70987                 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
70988
70989             } else {
70990                 // safe to delete
70991                 if (toDelete.indexOf(node) === -1) {
70992                     toDelete.push(node);
70993                 }
70994             }
70995         }
70996
70997         for (i = 0; i < toDelete.length; i++) {
70998             graph = actionDeleteNode(toDelete[i].id)(graph);
70999         }
71000
71001         return graph;
71002     };
71003
71004
71005     action.disabled = function(graph) {
71006         // check way isn't too bendy
71007         var way = graph.entity(wayId),
71008             nodes = graph.childNodes(way),
71009             points = nodes.map(function(n) { return projection(n.loc); }),
71010             startPoint = points[0],
71011             endPoint = points[points.length-1],
71012             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
71013             i;
71014
71015         if (threshold === 0) {
71016             return 'too_bendy';
71017         }
71018
71019         for (i = 1; i < points.length-1; i++) {
71020             var point = points[i],
71021                 u = positionAlongWay(point, startPoint, endPoint),
71022                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
71023                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
71024                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
71025
71026             // to bendy if point is off by 20% of total start/end distance in projected space
71027             if (isNaN(dist) || dist > threshold) {
71028                 return 'too_bendy';
71029             }
71030         }
71031     };
71032
71033
71034     action.transitionable = true;
71035
71036
71037     return action;
71038 }
71039
71040 // Remove the effects of `turn.restriction` on `turn`, which must have the
71041 // following structure:
71042 //
71043 //     {
71044 //         from: { node: <node ID>, way: <way ID> },
71045 //         via:  { node: <node ID> },
71046 //         to:   { node: <node ID>, way: <way ID> },
71047 //         restriction: <relation ID>
71048 //     }
71049 //
71050 // In the simple case, `restriction` is a reference to a `no_*` restriction
71051 // on the turn itself. In this case, it is simply deleted.
71052 //
71053 // The more complex case is where `restriction` references an `only_*`
71054 // restriction on a different turn in the same intersection. In that case,
71055 // that restriction is also deleted, but at the same time restrictions on
71056 // the turns other than the first two are created.
71057 //
71058 function actionUnrestrictTurn(turn) {
71059     return function(graph) {
71060         return actionDeleteRelation(turn.restriction)(graph);
71061     };
71062 }
71063
71064 /* Reflect the given area around its axis of symmetry */
71065 function actionReflect(reflectIds, projection) {
71066     var useLongAxis = true;
71067
71068
71069     // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
71070     // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
71071     function getSmallestSurroundingRectangle(graph, nodes) {
71072         var points = nodes.map(function(n) { return projection(n.loc); }),
71073             hull = d3polygonHull(points),
71074             centroid = d3polygonCentroid(hull),
71075             minArea = Infinity,
71076             ssrExtent = [],
71077             ssrAngle = 0,
71078             c1 = hull[0];
71079
71080         for (var i = 0; i < hull.length - 1; i++) {
71081             var c2 = hull[i + 1],
71082                 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
71083                 poly = geoRotate(hull, -angle, centroid),
71084                 extent$$1 = poly.reduce(function(extent$$1, point) {
71085                         return extent$$1.extend(geoExtent$$1(point));
71086                     }, geoExtent$$1()),
71087                 area$$1 = extent$$1.area();
71088
71089             if (area$$1 < minArea) {
71090                 minArea = area$$1;
71091                 ssrExtent = extent$$1;
71092                 ssrAngle = angle;
71093             }
71094             c1 = c2;
71095         }
71096
71097         return {
71098             poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
71099             angle: ssrAngle
71100         };
71101     }
71102
71103
71104     var action = function(graph, t) {
71105         if (t === null || !isFinite(t)) t = 1;
71106         t = Math.min(Math.max(+t, 0), 1);
71107
71108         var nodes = utilGetAllNodes(reflectIds, graph),
71109             ssr = getSmallestSurroundingRectangle(graph, nodes);
71110
71111         // Choose line pq = axis of symmetry.
71112         // The shape's surrounding rectangle has 2 axes of symmetry.
71113         // Reflect across the longer axis by default.
71114         var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
71115             q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
71116             p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
71117             q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
71118             p, q;
71119
71120         var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
71121         if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
71122             p = p1;
71123             q = q1;
71124         } else {
71125             p = p2;
71126             q = q2;
71127         }
71128
71129         // reflect c across pq
71130         // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
71131         var dx = q[0] - p[0];
71132         var dy = q[1] - p[1];
71133         var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
71134         var b = 2 * dx * dy / (dx * dx + dy * dy);
71135         for (var i = 0; i < nodes.length; i++) {
71136             var node = nodes[i];
71137             var c = projection(node.loc);
71138             var c2 = [
71139                 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
71140                 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
71141             ];
71142             var loc2 = projection.invert(c2);
71143             node = node.move(geoInterp(node.loc, loc2, t));
71144             graph = graph.replace(node);
71145         }
71146
71147         return graph;
71148     };
71149
71150
71151     action.useLongAxis = function(_) {
71152         if (!arguments.length) return useLongAxis;
71153         useLongAxis = _;
71154         return action;
71155     };
71156
71157
71158     action.transitionable = true;
71159
71160
71161     return action;
71162 }
71163
71164
71165
71166 var index$17 = Object.freeze({
71167         d3combobox: d3combobox,
71168         d3geoTile: d3geoTile,
71169         d3keybinding: d3keybinding
71170 });
71171
71172 /* export some legacy symbols: */
71173 var Connection = services.osm;
71174 var debug = false;
71175
71176
71177
71178
71179 var iD = Object.freeze({
71180         Connection: Connection,
71181         debug: debug,
71182         d3: index$2,
71183         lib: index$17,
71184         Context: coreContext,
71185         setAreaKeys: setAreaKeys,
71186         Difference: coreDifference,
71187         Graph: coreGraph$$1,
71188         History: coreHistory,
71189         Tree: coreTree,
71190         Entity: osmEntity$$1,
71191         Node: osmNode,
71192         Relation: osmRelation,
71193         Way: osmWay,
71194         BackgroundSource: rendererBackgroundSource,
71195         Background: rendererBackground,
71196         Features: rendererFeatures,
71197         Map: rendererMap,
71198         TileLayer: rendererTileLayer,
71199         Detect: utilDetect,
71200         actionAddEntity: actionAddEntity,
71201         actionAddMember: actionAddMember,
71202         actionAddMidpoint: actionAddMidpoint,
71203         actionAddVertex: actionAddVertex,
71204         actionChangeMember: actionChangeMember,
71205         actionChangePreset: actionChangePreset,
71206         actionChangeTags: actionChangeTags,
71207         actionCircularize: actionCircularize,
71208         actionConnect: actionConnect,
71209         actionCopyEntities: actionCopyEntities,
71210         actionDeleteMember: actionDeleteMember,
71211         actionDeleteMultiple: actionDeleteMultiple,
71212         actionDeleteNode: actionDeleteNode,
71213         actionDeleteRelation: actionDeleteRelation,
71214         actionDeleteWay: actionDeleteWay,
71215         actionDeprecateTags: actionDeprecateTags,
71216         actionDiscardTags: actionDiscardTags,
71217         actionDisconnect: actionDisconnect,
71218         actionJoin: actionJoin,
71219         actionMerge: actionMerge,
71220         actionMergePolygon: actionMergePolygon,
71221         actionMergeRemoteChanges: actionMergeRemoteChanges,
71222         actionMove: actionMove,
71223         actionMoveNode: actionMoveNode,
71224         actionNoop: actionNoop,
71225         actionOrthogonalize: actionOrthogonalize,
71226         actionRestrictTurn: actionRestrictTurn,
71227         actionReverse: actionReverse,
71228         actionRevert: actionRevert,
71229         actionRotate: actionRotate,
71230         actionSplit: actionSplit,
71231         actionStraighten: actionStraighten,
71232         actionUnrestrictTurn: actionUnrestrictTurn,
71233         actionReflect: actionReflect,
71234         behaviorAddWay: behaviorAddWay,
71235         behaviorBreathe: behaviorBreathe,
71236         behaviorCopy: behaviorCopy,
71237         behaviorDrag: behaviorDrag,
71238         behaviorDrawWay: behaviorDrawWay,
71239         behaviorDraw: behaviorDraw,
71240         behaviorEdit: behaviorEdit,
71241         behaviorHash: behaviorHash,
71242         behaviorHover: behaviorHover,
71243         behaviorLasso: behaviorLasso,
71244         behaviorOperation: behaviorOperation,
71245         behaviorPaste: behaviorPaste,
71246         behaviorSelect: behaviorSelect,
71247         behaviorTail: behaviorTail,
71248         coreContext: coreContext,
71249         coreDifference: coreDifference,
71250         coreGraph: coreGraph$$1,
71251         coreHistory: coreHistory,
71252         coreTree: coreTree,
71253         dataFeatureIcons: dataFeatureIcons,
71254         data: data,
71255         dataWikipedia: dataWikipedia,
71256         dataSuggestions: dataSuggestions,
71257         dataAddressFormats: dataAddressFormats,
71258         dataDeprecated: dataDeprecated,
71259         dataDiscarded: dataDiscarded,
71260         dataLocales: dataLocales,
71261         dataPhoneFormats: dataPhoneFormats,
71262         dataImperial: dataImperial,
71263         dataDriveLeft: dataDriveLeft,
71264         dataEn: en,
71265         geoAngle: geoAngle,
71266         geoChooseEdge: geoChooseEdge,
71267         geoCross: geoCross,
71268         geoEdgeEqual: geoEdgeEqual,
71269         geoEuclideanDistance: geoEuclideanDistance,
71270         geoExtent: geoExtent$$1,
71271         geoInterp: geoInterp,
71272         geoRawMercator: geoRawMercator,
71273         geoRoundCoords: geoRoundCoords,
71274         geoRotate: geoRotate,
71275         geoLatToMeters: geoLatToMeters,
71276         geoLineIntersection: geoLineIntersection,
71277         geoLonToMeters: geoLonToMeters,
71278         geoMetersToLat: geoMetersToLat,
71279         geoMetersToLon: geoMetersToLon,
71280         geoMetersToOffset: geoMetersToOffset,
71281         geoOffsetToMeters: geoOffsetToMeters,
71282         geoPathIntersections: geoPathIntersections,
71283         geoPathLength: geoPathLength,
71284         geoPointInPolygon: geoPointInPolygon,
71285         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
71286         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
71287         geoSphericalDistance: geoSphericalDistance,
71288         modeAddArea: modeAddArea$$1,
71289         modeAddLine: modeAddLine$$1,
71290         modeAddPoint: modeAddPoint$$1,
71291         modeBrowse: modeBrowse,
71292         modeDragNode: modeDragNode$$1,
71293         modeDrawArea: modeDrawArea,
71294         modeDrawLine: modeDrawLine,
71295         modeMove: modeMove$$1,
71296         modeRotate: modeRotate$$1,
71297         modeSave: modeSave$$1,
71298         modeSelect: modeSelect,
71299         operationCircularize: operationCircularize,
71300         operationContinue: operationContinue,
71301         operationDelete: operationDelete,
71302         operationDisconnect: operationDisconnect,
71303         operationMerge: operationMerge,
71304         operationMove: operationMove,
71305         operationOrthogonalize: operationOrthogonalize,
71306         operationReflectShort: operationReflectShort,
71307         operationReflectLong: operationReflectLong,
71308         operationReverse: operationReverse,
71309         operationRotate: operationRotate,
71310         operationSplit: operationSplit,
71311         operationStraighten: operationStraighten,
71312         osmEntity: osmEntity$$1,
71313         osmNode: osmNode,
71314         osmRelation: osmRelation,
71315         osmWay: osmWay,
71316         osmIntersection: osmIntersection,
71317         osmTurn: osmTurn,
71318         osmInferRestriction: osmInferRestriction,
71319         osmLanes: osmLanes,
71320         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
71321         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
71322         osmJoinWays: osmJoinWays,
71323         osmOneWayTags: osmOneWayTags,
71324         osmPavedTags: osmPavedTags,
71325         osmIsInterestingTag: osmIsInterestingTag,
71326         presetCategory: presetCategory,
71327         presetCollection: presetCollection,
71328         presetField: presetField,
71329         presetPreset: presetPreset,
71330         presetIndex: presetIndex,
71331         rendererBackgroundSource: rendererBackgroundSource,
71332         rendererBackground: rendererBackground,
71333         rendererFeatures: rendererFeatures,
71334         rendererMap: rendererMap,
71335         rendererTileLayer: rendererTileLayer,
71336         services: services,
71337         svgAreas: svgAreas$$1,
71338         svgDebug: svgDebug,
71339         svgDefs: svgDefs,
71340         svgGpx: svgGpx,
71341         svgIcon: svgIcon,
71342         svgLabels: svgLabels,
71343         svgLayers: svgLayers,
71344         svgLines: svgLines$$1,
71345         svgMapillaryImages: svgMapillaryImages,
71346         svgMapillarySigns: svgMapillarySigns,
71347         svgMidpoints: svgMidpoints$$1,
71348         svgOneWaySegments: svgOneWaySegments,
71349         svgOsm: svgOsm,
71350         svgPath: svgPath,
71351         svgPointTransform: svgPointTransform,
71352         svgPoints: svgPoints$$1,
71353         svgRelationMemberTags: svgRelationMemberTags,
71354         svgTagClasses: svgTagClasses,
71355         svgTurns: svgTurns,
71356         svgVertices: svgVertices$$1,
71357         uiFields: uiFields,
71358         uiFieldDefaultcheck: uiFieldCheck,
71359         uiFieldCheck: uiFieldCheck,
71360         uiFieldTypeCombo: uiFieldCombo,
71361         uiFieldMultiCombo: uiFieldCombo,
71362         uiFieldNetworkCombo: uiFieldCombo,
71363         uiFieldCombo: uiFieldCombo,
71364         uiFieldUrl: uiFieldText,
71365         uiFieldNumber: uiFieldText,
71366         uiFieldTel: uiFieldText,
71367         uiFieldEmail: uiFieldText,
71368         uiFieldText: uiFieldText,
71369         uiFieldAccess: uiFieldAccess,
71370         uiFieldAddress: uiFieldAddress,
71371         uiFieldCycleway: uiFieldCycleway,
71372         uiFieldLanes: uiFieldLanes,
71373         uiFieldLocalized: uiFieldLocalized,
71374         uiFieldMaxspeed: uiFieldMaxspeed,
71375         uiFieldRadio: uiFieldRadio,
71376         uiFieldRestrictions: uiFieldRestrictions,
71377         uiFieldTextarea: uiFieldTextarea,
71378         uiFieldWikipedia: uiFieldWikipedia,
71379         uiIntro: uiIntro,
71380         uiInit: uiInit,
71381         uiAccount: uiAccount,
71382         uiAttribution: uiAttribution,
71383         uiBackground: uiBackground,
71384         uiCmd: uiCmd,
71385         uiCommit: uiCommit,
71386         uiConfirm: uiConfirm,
71387         uiConflicts: uiConflicts,
71388         uiContributors: uiContributors,
71389         uiDisclosure: uiDisclosure,
71390         uiEntityEditor: uiEntityEditor,
71391         uiFeatureInfo: uiFeatureInfo,
71392         uiFeatureList: uiFeatureList,
71393         uiFlash: uiFlash,
71394         uiFullScreen: uiFullScreen,
71395         uiGeolocate: uiGeolocate,
71396         uiHelp: uiHelp,
71397         uiInfo: uiInfo,
71398         uiInspector: uiInspector,
71399         uiLasso: uiLasso,
71400         uiLoading: uiLoading,
71401         uiMapData: uiMapData,
71402         uiMapInMap: uiMapInMap,
71403         uiModal: uiModal,
71404         uiModes: uiModes,
71405         uiNotice: uiNotice,
71406         uiPreset: uiPreset,
71407         uiPresetIcon: uiPresetIcon,
71408         uiPresetList: uiPresetList,
71409         uiRadialMenu: uiRadialMenu,
71410         uiRawMemberEditor: uiRawMemberEditor,
71411         uiRawMembershipEditor: uiRawMembershipEditor,
71412         uiRawTagEditor: uiRawTagEditor,
71413         uiRestore: uiRestore,
71414         uiSave: uiSave,
71415         uiScale: uiScale,
71416         uiSelectionList: uiSelectionList,
71417         uiSidebar: uiSidebar,
71418         uiSourceSwitch: uiSourceSwitch,
71419         uiSpinner: uiSpinner,
71420         uiSplash: uiSplash,
71421         uiStatus: uiStatus,
71422         uiSuccess: uiSuccess,
71423         uiTagReference: uiTagReference,
71424         uiToggle: uiToggle,
71425         uiTooltipHtml: uiTooltipHtml,
71426         uiUndoRedo: uiUndoRedo,
71427         uiViewOnOSM: uiViewOnOSM,
71428         uiZoom: uiZoom,
71429         utilTagText: utilTagText,
71430         utilEntitySelector: utilEntitySelector,
71431         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
71432         utilGetAllNodes: utilGetAllNodes,
71433         utilDisplayName: utilDisplayName,
71434         utilDisplayNameForPath: utilDisplayNameForPath,
71435         utilDisplayType: utilDisplayType,
71436         utilStringQs: utilStringQs,
71437         utilQsString: utilQsString,
71438         utilPrefixDOMProperty: utilPrefixDOMProperty,
71439         utilPrefixCSSProperty: utilPrefixCSSProperty,
71440         utilSetTransform: utilSetTransform,
71441         utilEditDistance: utilEditDistance,
71442         utilFastMouse: utilFastMouse,
71443         utilGetPrototypeOf: utilGetPrototypeOf,
71444         utilAsyncMap: utilAsyncMap,
71445         utilWrap: utilWrap,
71446         utilFunctor: utilFunctor,
71447         utilSessionMutex: utilSessionMutex,
71448         utilSuggestNames: utilSuggestNames,
71449         utilTriggerEvent: utilTriggerEvent,
71450         utilGetSetValue: utilGetSetValue,
71451         d3combobox: d3combobox,
71452         d3geoTile: d3geoTile,
71453         d3keybinding: d3keybinding,
71454         validationDeprecatedTag: validationDeprecatedTag,
71455         validationDisconnectedHighway: validationDisconnectedHighway,
71456         validationManyDeletions: validationManyDeletions,
71457         validationMissingTag: validationMissingTag,
71458         validationTagSuggestsArea: validationTagSuggestsArea
71459 });
71460
71461 window.iD = iD;
71462
71463 }());
71464 //# sourceMappingURL=iD.js.map