]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
681ebc840c3f16dc3f489fb398586da68c506324
[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"},"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/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":"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":"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":"lu.geoportail.opendata.basemap","name":"Luxembourg Geoportail Basemap","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/basemap/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/carte-de-base-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.cadastre","name":"Luxembourg Geoportail Cadastre","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/cadastre/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/plan-cadastral-numerise-pcn-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2010","name":"Luxembourg Geoportail Ortho 2010","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2010/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2013","name":"Luxembourg Geoportail Ortho 2013","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2013/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"lu.geoportail.opendata.ortho2016","name":"Luxembourg Geoportail Ortho 2016","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":"lu.geoportail.opendata.topo","name":"Luxembourg Geoportail Topographical Map","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/topo/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/cartes-topographiques-services-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie"},{"id":"Mapbox","name":"Mapbox Satellite","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh7ifmo/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","description":"Satellite and aerial imagery.","scaleExtent":[0,19],"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true},{"id":"geodata.md.gov-MD_SixInchImagery","name":"MD 2014 6 Inch Aerial Imagery","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/MD_SixInchImagery/http://geodata.md.gov/imap/services/Imagery/MD_SixInchImagery/MapServer/WmsServer","description":"Six Inch resolution aerial imagery for the State of Maryland","scaleExtent":[0,20],"polygon":[[[-76.234131,37.920368],[-76.598053,38.158317],[-76.940002,38.270532],[-77.038193,38.413786],[-77.23526,38.33627],[-77.312164,38.410558],[-77.262726,38.566422],[-77.042999,38.713376],[-77.049866,38.793697],[-76.92627,38.892503],[-77.040939,38.984499],[-77.12162,38.925229],[-77.150116,38.955137],[-77.252426,38.975425],[-77.259293,39.024252],[-77.34581,39.054918],[-77.461853,39.070379],[-77.537384,39.139647],[-77.474213,39.224807],[-77.572746,39.304284],[-77.723465,39.328986],[-77.777023,39.463234],[-77.861481,39.516225],[-77.840881,39.608862],[-77.956238,39.59299],[-78.166351,39.695564],[-78.270035,39.621557],[-78.338699,39.640066],[-78.466415,39.523641],[-78.662796,39.540058],[-78.798752,39.606217],[-78.9814,39.446799],[-79.06723,39.476486],[-79.485054,39.199536],[-79.485569,39.72158],[-75.788359,39.721811],[-75.690994,38.460579],[-75.049238,38.458159],[-75.049839,38.402218],[-75.081511,38.323208],[-75.097733,38.309066],[-75.186996,38.097551],[-75.23798,38.022402],[-75.61821,37.989669],[-75.863686,37.909534],[-76.234131,37.920368]]],"terms_url":"http://imap.maryland.gov/Pages/imagery-products.aspx","terms_text":"DoIT, MD iMap, MDP"},{"id":"geodata.md.gov-MD_ColorBasemap","name":"MD Transportation Basemap","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/MD_ColorBasemap/http://geodata.md.gov/imap/services/Transportation/MD_ColorBasemap/MapServer/WmsServer","description":"Maryland State Highway Administration road features and additional Maryland focused landmarks","polygon":[[[-76.234131,37.920368],[-76.598053,38.158317],[-76.940002,38.270532],[-77.038193,38.413786],[-77.23526,38.33627],[-77.312164,38.410558],[-77.262726,38.566422],[-77.042999,38.713376],[-77.049866,38.793697],[-76.92627,38.892503],[-77.040939,38.984499],[-77.12162,38.925229],[-77.150116,38.955137],[-77.252426,38.975425],[-77.259293,39.024252],[-77.34581,39.054918],[-77.461853,39.070379],[-77.537384,39.139647],[-77.474213,39.224807],[-77.572746,39.304284],[-77.723465,39.328986],[-77.777023,39.463234],[-77.861481,39.516225],[-77.840881,39.608862],[-77.956238,39.59299],[-78.166351,39.695564],[-78.270035,39.621557],[-78.338699,39.640066],[-78.466415,39.523641],[-78.662796,39.540058],[-78.798752,39.606217],[-78.9814,39.446799],[-79.06723,39.476486],[-79.485054,39.199536],[-79.485569,39.72158],[-75.788359,39.721811],[-75.690994,38.460579],[-75.049238,38.458159],[-75.049839,38.402218],[-75.081511,38.323208],[-75.097733,38.309066],[-75.186996,38.097551],[-75.23798,38.022402],[-75.61821,37.989669],[-75.863686,37.909534],[-76.234131,37.920368]]],"terms_url":"http://imap.maryland.gov/Pages/imagery-products.aspx","terms_text":"DoIT, MD iMap, MDP"},{"id":"New_and_Misaligned_TIGER_Roads-2013","name":"New & Misaligned TIGER Roads","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/enf.e0b8291e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q","description":"At zoom level 16+, public domain map data from the US Census. At lower zooms, only changes since 2006 minus changes already incorporated into OpenStreetMap","scaleExtent":[0,22],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]],"overlay":true},{"id":"geodata.state.nj.us-Infrared2015","name":"NJ 2015 Aerial Imagery (Infrared)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Infrared2015/http://geodata.state.nj.us/imagerywms/Infrared2015","description":"Digital orthophotography of New Jersey, Near Infrared, 1 foot resolution","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-74.041049,41.059086],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-73.933408,40.882075],[-73.933408,40.882075],[-74.011459,40.75558],[-74.024543,40.709436],[-74.066048,40.651732],[-74.152222,40.638967],[-74.183121,40.644568],[-74.200459,40.631281],[-74.199257,40.598444],[-74.21505,40.558026],[-74.246807,40.548113],[-74.24715,40.519541],[-74.267578,40.489651],[-74.26054,40.469282],[-74.199257,40.445641],[-74.181061,40.460401],[-74.136429,40.459095],[-73.997555,40.413496],[-74.026566,40.47777],[-74.003906,40.484037],[-73.977814,40.452042],[-73.964767,40.33189],[-74.088364,39.756824],[-74.356842,39.383406],[-74.609528,39.215231],[-74.776382,38.998909],[-74.863586,38.931639],[-74.931221,38.920688],[-74.980316,38.930304],[-74.960747,39.00798],[-74.905472,39.100226],[-74.899979,39.164141],[-75.101166,39.201398],[-75.135498,39.171062],[-75.425949,39.378099],[-75.475044,39.43195],[-75.543365,39.457403],[-75.552292,39.482845],[-75.538902,39.541911],[-75.519676,39.56997],[-75.571175,39.608069],[-75.577698,39.625524],[-75.539932,39.656456],[-75.472984,39.747454],[-75.466253,39.750761],[-75.466252,39.750762],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466251,39.750764],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-75.466249,39.750769],[-75.466249,39.750769],[-75.465088,39.764478],[-75.415041,39.801786],[-75.324669,39.858891],[-75.246048,39.864689],[-75.143738,39.900255],[-75.142365,39.957912],[-75.07061,39.987117],[-75.056534,40.008683],[-74.935341,40.072555],[-74.86599,40.085427]]],"terms_url":"https://njgin.state.nj.us/NJ_NJGINExplorer/ShowMetadata.jsp?docId={E30775F2-6370-4525-8E68-C371ED29BBB3}","terms_text":"NJ Office of Information Technology (NJOIT), Office of Geographic Information Systems (OGIS)"},{"id":"geodata.state.nj.us-Natural2015","name":"NJ 2015 Aerial Imagery (Natural Color)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Natural2015/http://geodata.state.nj.us/imagerywms/Natural2015","description":"Digital orthophotography of New Jersey, Natural Color, 1 foot resolution","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-74.041049,41.059086],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-73.933408,40.882075],[-73.933408,40.882075],[-74.011459,40.75558],[-74.024543,40.709436],[-74.066048,40.651732],[-74.152222,40.638967],[-74.183121,40.644568],[-74.200459,40.631281],[-74.199257,40.598444],[-74.21505,40.558026],[-74.246807,40.548113],[-74.24715,40.519541],[-74.267578,40.489651],[-74.26054,40.469282],[-74.199257,40.445641],[-74.181061,40.460401],[-74.136429,40.459095],[-73.997555,40.413496],[-74.026566,40.47777],[-74.003906,40.484037],[-73.977814,40.452042],[-73.964767,40.33189],[-74.088364,39.756824],[-74.356842,39.383406],[-74.609528,39.215231],[-74.776382,38.998909],[-74.863586,38.931639],[-74.931221,38.920688],[-74.980316,38.930304],[-74.960747,39.00798],[-74.905472,39.100226],[-74.899979,39.164141],[-75.101166,39.201398],[-75.135498,39.171062],[-75.425949,39.378099],[-75.475044,39.43195],[-75.543365,39.457403],[-75.552292,39.482845],[-75.538902,39.541911],[-75.519676,39.56997],[-75.571175,39.608069],[-75.577698,39.625524],[-75.539932,39.656456],[-75.472984,39.747454],[-75.466253,39.750761],[-75.466252,39.750762],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466251,39.750764],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-75.466249,39.750769],[-75.466249,39.750769],[-75.465088,39.764478],[-75.415041,39.801786],[-75.324669,39.858891],[-75.246048,39.864689],[-75.143738,39.900255],[-75.142365,39.957912],[-75.07061,39.987117],[-75.056534,40.008683],[-74.935341,40.072555],[-74.86599,40.085427]]],"terms_url":"https://njgin.state.nj.us/NJ_NJGINExplorer/ShowMetadata.jsp?docId={CDC67AB8-ADA1-4B4B-9087-67A82CB9151C}","terms_text":"NJ Office of Information Technology (NJOIT), Office of Geographic Information Systems (OGIS)"},{"id":"NLS-Bartholomew-hfinch-hist","name":"NLS - Bartholomew Half Inch, 1897-1907","type":"tms","template":"http://geo.nls.uk/mapdata2/bartholomew/great_britain/{zoom}/{x}/{-y}.png","scaleExtent":[0,15],"polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-7th_Series","name":"NLS - OS 1-inch 7th Series 1955-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/seventh/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-1st_Series","name":"NLS - OS 1:25k 1st Series 1937-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25000/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-4.7157244,54.6796556],[-4.6850662,54.6800268],[-4.6835779,54.6623245],[-4.7148782,54.6615818],[-4.7157244,54.6796556]],[[-3.7085748,58.3371151],[-3.5405937,58.3380684],[-3.5315137,58.1608002],[-3.3608086,58.1622372],[-3.3653486,58.252173],[-3.1610473,58.2536063],[-3.1610473,58.3261509],[-3.0275704,58.3271045],[-3.0366505,58.6139001],[-3.0021463,58.614373],[-3.0030543,58.7036341],[-3.4180129,58.7003322],[-3.4171049,58.6290293],[-3.7240109,58.6266658],[-3.7231029,58.606806],[-4.2361262,58.5992374],[-4.2334022,58.5092347],[-3.88836,58.5144516],[-3.8829119,58.4261327],[-3.7158389,58.4270836],[-3.7085748,58.3371151]],[[-6.46676,49.9943621],[-6.1889102,50.004868],[-6.1789222,49.8967815],[-6.3169391,49.8915171],[-6.312399,49.8200979],[-6.4504159,49.8159968],[-6.46676,49.9943621]],[[-5.6453263,50.2029809],[-5.7801329,50.2014076],[-5.7637888,50.0197267],[-5.3479221,50.0290604],[-5.3388421,49.9414854],[-5.024672,49.9473287],[-5.0355681,50.0383923],[-5.0010639,50.0453901],[-4.9974319,50.1304478],[-4.855783,50.13394],[-4.861231,50.206057],[-4.6546085,50.2140172],[-4.6558926,50.3018616],[-4.5184924,50.3026818],[-4.51464,50.325642],[-4.2488284,50.3264618],[-4.2488284,50.3100631],[-4.10886,50.3141633],[-4.1062917,50.2411267],[-3.9648088,50.2432047],[-3.9640778,50.2254158],[-3.8522287,50.2273626],[-3.8503757,50.1552563],[-3.6921809,50.1572487],[-3.5414602,50.1602198],[-3.5465781,50.3226814],[-3.4068012,50.3241013],[-3.4165761,50.5892711],[-3.2746691,50.5962721],[-3.2749172,50.6106323],[-2.9971742,50.613972],[-2.9896008,50.688537],[-2.7120266,50.690565],[-2.710908,50.6195964],[-2.5695473,50.6157538],[-2.5651019,50.5134083],[-2.4014463,50.513379],[-2.3940583,50.6160348],[-2.2894123,50.6147436],[-2.2876184,50.6008549],[-2.1477855,50.6048506],[-2.1451013,50.5325437],[-1.9335117,50.5347477],[-1.9362139,50.6170445],[-1.8573025,50.6228094],[-1.8554865,50.709139],[-1.6066929,50.709139],[-1.6085089,50.6239615],[-1.4450678,50.6228094],[-1.4432518,50.5317039],[-1.1545059,50.5293951],[-1.1472419,50.6170485],[-1.011041,50.6205051],[-1.011041,50.7056889],[-0.704135,50.7045388],[-0.700503,50.7769401],[-0.5860943,50.7723465],[-0.5879103,50.7907181],[-0.0149586,50.7798108],[-0.0185906,50.7625836],[0.0967261,50.7620093],[0.0921861,50.6913106],[0.3046595,50.6890096],[0.3101075,50.7757917],[0.5511831,50.7726336],[0.5529991,50.8432096],[0.695556,50.8403428],[0.696464,50.8592608],[0.9852099,50.8523824],[0.9906579,50.9417226],[1.0160821,50.9411504],[1.0215301,51.0303204],[1.2812198,51.0240383],[1.2848518,51.0948044],[1.4277848,51.0948044],[1.4386809,51.2882859],[1.4713691,51.2871502],[1.4804492,51.3994534],[1.1590151,51.4073836],[1.1590151,51.3869889],[1.0191822,51.3903886],[1.0228142,51.4798247],[0.8793493,51.4843484],[0.8829813,51.5566675],[1.0264462,51.5544092],[1.0373423,51.7493319],[1.2607117,51.7482076],[1.2661598,51.8279642],[1.3351682,51.8335756],[1.3478803,51.9199021],[1.4840812,51.9199021],[1.4986093,52.0038271],[1.6438902,52.0027092],[1.6656823,52.270221],[1.7310588,52.270221],[1.7528509,52.4465637],[1.8254914,52.4476705],[1.8345714,52.624408],[1.7690346,52.6291402],[1.7741711,52.717904],[1.6996925,52.721793],[1.706113,52.8103687],[1.559724,52.8165777],[1.5648605,52.9034116],[1.4184715,52.9103818],[1.4223238,52.9281894],[1.3439928,52.9289635],[1.3491293,53.0001194],[0.4515789,53.022589],[0.4497629,52.9351139],[0.3789384,52.9351139],[0.3716744,52.846365],[0.2227614,52.8496552],[0.2336575,52.9329248],[0.3062979,52.9351139],[0.308114,53.022589],[0.3807544,53.0236813],[0.3993708,53.2933729],[0.3248922,53.2987454],[0.3274604,53.3853782],[0.2504136,53.38691],[0.2581183,53.4748924],[0.1862079,53.4779494],[0.1913443,53.6548777],[0.1502527,53.6594436],[0.1528209,53.7666003],[0.0012954,53.7734308],[0.0025796,53.8424326],[-0.0282392,53.841675],[-0.0226575,53.9311501],[-0.1406983,53.9322193],[-0.1416063,54.0219323],[-0.1706625,54.0235326],[-0.1679384,54.0949482],[-0.0126694,54.0912206],[-0.0099454,54.1811226],[-0.1615824,54.1837795],[-0.1606744,54.2029038],[-0.2405789,54.2034349],[-0.2378549,54.2936234],[-0.3894919,54.2941533],[-0.3857497,54.3837321],[-0.461638,54.3856364],[-0.4571122,54.4939066],[-0.6105651,54.4965434],[-0.6096571,54.5676704],[-0.7667421,54.569776],[-0.7640181,54.5887213],[-0.9192871,54.5908258],[-0.9148116,54.6608348],[-1.1485204,54.6634343],[-1.1472363,54.7528316],[-1.2268514,54.7532021],[-1.2265398,54.8429879],[-1.2991803,54.8435107],[-1.2991803,54.9333391],[-1.3454886,54.9354258],[-1.3436726,55.0234878],[-1.3772688,55.0255698],[-1.3754528,55.1310877],[-1.4997441,55.1315727],[-1.4969272,55.2928323],[-1.5296721,55.2942946],[-1.5258198,55.6523803],[-1.7659492,55.6545537],[-1.7620968,55.7435626],[-1.9688392,55.7435626],[-1.9698023,55.8334505],[-2.0019051,55.8336308],[-2.0015841,55.9235526],[-2.1604851,55.9240613],[-2.1613931,55.9413549],[-2.3202942,55.9408463],[-2.3212022,56.0145126],[-2.5627317,56.0124824],[-2.5645477,56.1022207],[-2.9658863,56.0991822],[-2.9667943,56.1710304],[-2.4828272,56.1755797],[-2.4882752,56.2856078],[-2.5645477,56.2835918],[-2.5681798,56.3742075],[-2.7261728,56.3732019],[-2.7316208,56.4425301],[-2.6190281,56.4425301],[-2.6153961,56.5317671],[-2.453771,56.5347715],[-2.4534686,56.6420248],[-2.4062523,56.6440218],[-2.3953562,56.7297964],[-2.2936596,56.7337811],[-2.2972916,56.807423],[-2.1629067,56.8113995],[-2.1592747,56.9958425],[-1.9922016,57.0017771],[-2.0067297,57.2737477],[-1.9195612,57.2757112],[-1.9304572,57.3482876],[-1.8106005,57.3443682],[-1.7997044,57.4402728],[-1.6616875,57.4285429],[-1.6689516,57.5398256],[-1.7452241,57.5398256],[-1.7524881,57.6313302],[-1.8287606,57.6332746],[-1.8287606,57.7187255],[-3.1768526,57.7171219],[-3.1794208,57.734264],[-3.5134082,57.7292105],[-3.5129542,57.7112683],[-3.7635638,57.7076303],[-3.7598539,57.635713],[-3.8420372,57.6343382],[-3.8458895,57.6178365],[-3.9794374,57.6157733],[-3.9794374,57.686544],[-3.8150708,57.689976],[-3.817639,57.7968899],[-3.6853753,57.7989429],[-3.6892276,57.8891567],[-3.9383458,57.8877915],[-3.9421981,57.9750592],[-3.6943641,57.9784638],[-3.6969323,58.0695865],[-4.0372226,58.0641528],[-4.0346543,57.9730163],[-4.2003051,57.9702923],[-4.1832772,57.7012869],[-4.518752,57.6951111],[-4.5122925,57.6050682],[-4.6789116,57.6016628],[-4.666022,57.4218334],[-3.6677696,57.4394729],[-3.671282,57.5295384],[-3.3384979,57.5331943],[-3.3330498,57.4438859],[-2.8336466,57.4485275],[-2.8236396,56.9992706],[-2.3305398,57.0006693],[-2.3298977,56.9113932],[-2.6579889,56.9092901],[-2.6559637,56.8198406],[-2.8216747,56.8188467],[-2.8184967,56.7295397],[-3.1449248,56.7265508],[-3.1435628,56.6362749],[-3.4679089,56.6350265],[-3.474265,56.7238108],[-3.8011471,56.7188284],[-3.785711,56.4493026],[-3.946428,56.4457896],[-3.9428873,56.2659777],[-4.423146,56.2588459],[-4.4141572,56.0815506],[-4.8944159,56.0708008],[-4.8791072,55.8896994],[-5.1994158,55.8821374],[-5.1852906,55.7023791],[-5.0273445,55.7067203],[-5.0222081,55.6879046],[-4.897649,55.6907999],[-4.8880181,55.6002822],[-4.7339244,55.6046348],[-4.7275038,55.5342082],[-4.773732,55.5334815],[-4.7685955,55.4447227],[-4.8494947,55.4418092],[-4.8405059,55.3506535],[-4.8700405,55.3513836],[-4.8649041,55.2629462],[-4.9920314,55.2592875],[-4.9907473,55.1691779],[-5.0600894,55.1655105],[-5.0575212,55.0751884],[-5.2141831,55.0722477],[-5.1991766,54.8020337],[-5.0466316,54.8062205],[-5.0502636,54.7244996],[-4.9703591,54.7203043],[-4.9776232,54.6215905],[-4.796022,54.6342056],[-4.796022,54.7307917],[-4.8977186,54.7265971],[-4.9086147,54.8145928],[-4.8069181,54.8166856],[-4.8105501,54.7915648],[-4.6943253,54.7978465],[-4.6761652,54.7244996],[-4.5744686,54.7244996],[-4.5599405,54.6426135],[-4.3093309,54.6384098],[-4.3333262,54.8229889],[-4.2626999,54.8274274],[-4.2549952,54.7348587],[-3.8338058,54.7400481],[-3.836374,54.8141105],[-3.7118149,54.8133706],[-3.7143831,54.8318654],[-3.5346072,54.8355633],[-3.5271039,54.9066228],[-3.4808758,54.9084684],[-3.4776655,54.7457328],[-3.5874573,54.744621],[-3.5836049,54.6546166],[-3.7107322,54.6531308],[-3.6991752,54.4550407],[-3.5746161,54.4572801],[-3.5759002,54.3863042],[-3.539945,54.3855564],[-3.5386609,54.297224],[-3.46033,54.2957252],[-3.4590458,54.2079507],[-3.3807149,54.2102037],[-3.381999,54.1169788],[-3.302878,54.1160656],[-3.300154,54.0276224],[-3.1013007,54.0292224],[-3.093596,53.6062158],[-3.2065981,53.6016441],[-3.2091663,53.4917753],[-3.2451215,53.4887193],[-3.2348486,53.4045934],[-3.5276266,53.3999999],[-3.5343966,53.328481],[-3.6488053,53.3252272],[-3.6527308,53.3057716],[-3.7271873,53.3046865],[-3.7315003,53.3945257],[-3.9108315,53.3912769],[-3.9071995,53.3023804],[-3.9521457,53.3015665],[-3.9566724,53.3912183],[-4.1081979,53.3889209],[-4.1081979,53.4072967],[-4.2622916,53.4065312],[-4.2635757,53.4753707],[-4.638537,53.4677274],[-4.6346847,53.3812621],[-4.7091633,53.3774321],[-4.7001745,53.1954965],[-4.5499332,53.1962658],[-4.5435126,53.1092488],[-4.3919871,53.1100196],[-4.3855666,53.0236002],[-4.6115707,53.0205105],[-4.603866,52.9284932],[-4.7566756,52.9261709],[-4.7476868,52.8370555],[-4.8208813,52.8331768],[-4.8208813,52.7446476],[-4.3701572,52.7539749],[-4.3765778,52.8401583],[-4.2314728,52.8455875],[-4.2237682,52.7586379],[-4.1056297,52.7570836],[-4.1015192,52.6714874],[-4.1487355,52.6703862],[-4.1305754,52.4008596],[-4.1995838,52.3986435],[-4.2050319,52.3110195],[-4.3466808,52.303247],[-4.3484968,52.2365693],[-4.4901457,52.2332328],[-4.4883297,52.2098702],[-4.6572188,52.2098702],[-4.6590348,52.1385939],[-4.7788916,52.13525],[-4.7807076,52.1162967],[-4.9259885,52.1140663],[-4.9187245,52.0392855],[-5.2365265,52.0314653],[-5.2347105,51.9442339],[-5.3473032,51.9408755],[-5.3473032,51.9195995],[-5.4925842,51.9162392],[-5.4853201,51.8265386],[-5.1983903,51.8321501],[-5.1893102,51.7625177],[-5.335825,51.7589528],[-5.3281204,51.6686495],[-5.1836575,51.6730296],[-5.1836575,51.6539134],[-5.0674452,51.6578966],[-5.0603825,51.5677905],[-4.5974594,51.5809588],[-4.60388,51.6726314],[-4.345773,51.6726314],[-4.3355001,51.4962964],[-3.9528341,51.5106841],[-3.9425611,51.5905333],[-3.8809237,51.5953198],[-3.8706508,51.5074872],[-3.7679216,51.4978952],[-3.7550805,51.4242895],[-3.5855774,51.41468],[-3.5778727,51.3329177],[-3.0796364,51.3329177],[-3.0770682,51.2494018],[-3.7216935,51.2381477],[-3.7216935,51.2558315],[-3.8706508,51.2558315],[-3.8680825,51.2365398],[-4.2944084,51.2252825],[-4.289272,51.0496352],[-4.5692089,51.0431767],[-4.5624122,50.9497388],[-4.5905604,50.9520269],[-4.5896524,50.8627065],[-4.6296046,50.8592677],[-4.6226411,50.7691513],[-4.6952816,50.7680028],[-4.6934655,50.6967379],[-4.8342064,50.6938621],[-4.8296664,50.6046231],[-4.9676833,50.6000126],[-4.9685913,50.5821427],[-5.1084242,50.5786832],[-5.1029762,50.4892254],[-5.1311244,50.48807],[-5.1274923,50.4163798],[-5.2664172,50.4117509],[-5.2609692,50.3034214],[-5.5124868,50.2976214],[-5.5061308,50.2256428],[-5.6468717,50.2209953],[-5.6453263,50.2029809]],[[-5.1336607,55.2630226],[-5.1021999,55.2639372],[-5.0999527,55.2458239],[-5.1322161,55.2446343],[-5.1336607,55.2630226]],[[-5.6431878,55.5095745],[-5.4861028,55.5126594],[-5.4715747,55.3348829],[-5.6277517,55.3302345],[-5.6431878,55.5095745]],[[-4.7213517,51.2180246],[-4.5804201,51.2212417],[-4.5746416,51.1306736],[-4.7174993,51.1280545],[-4.7213517,51.2180246]],[[-5.1608796,55.4153626],[-5.0045387,55.4190069],[-5.0184798,55.6153521],[-5.1755648,55.6138137],[-5.1608796,55.4153626]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-25inch-hist","name":"NLS - OS 25-inch (Scotland), 1892-1905","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25_inch/scotland_1/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-9.25,54.43],[-9.25,61.12],[0.22,61.12],[0.22,54.43],[-9.25,54.43]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLS-OS-6inch-Scotland-hist","name":"NLS - OS 6-inch Scotland 1842-82","type":"tms","template":"http://geo.nls.uk/maps/os/six_inch/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-5.2112173,54.8018593],[-5.0642752,54.8026508],[-5.0560354,54.6305176],[-4.3158316,54.6297227],[-4.3117117,54.7448258],[-3.8530325,54.7464112],[-3.8530325,54.8034424],[-3.5522818,54.8034424],[-3.5522818,54.8374644],[-3.468511,54.8406277],[-3.4657644,54.8983158],[-3.3847403,54.8991055],[-3.3888601,54.9559214],[-3.0920786,54.9539468],[-3.0392359,54.9923274],[-3.0212713,55.0493881],[-2.9591232,55.0463283],[-2.9202807,55.0666294],[-2.7857081,55.068652],[-2.7852225,55.0914426],[-2.7337562,55.0922761],[-2.737616,55.151204],[-2.7648395,55.1510672],[-2.7013114,55.1722505],[-2.6635459,55.2192808],[-2.6460364,55.2188891],[-2.629042,55.2233933],[-2.6317886,55.2287781],[-2.6235488,55.2446345],[-2.6197723,55.2454663],[-2.6099017,55.2454174],[-2.6099876,55.2486466],[-2.6408121,55.2590039],[-2.6247896,55.2615631],[-2.6045186,55.2823081],[-2.5693176,55.296132],[-2.5479542,55.3121617],[-2.5091116,55.3234891],[-2.4780376,55.3494471],[-2.4421083,55.3533118],[-2.4052079,55.3439256],[-2.3726772,55.3447539],[-2.3221819,55.3687665],[-2.3241241,55.3999337],[-2.2576062,55.425015],[-2.1985547,55.4273529],[-2.1484296,55.4717466],[-2.1944348,55.484199],[-2.2040479,55.529306],[-2.2960584,55.6379722],[-2.2177808,55.6379722],[-2.1059266,55.7452498],[-1.9716874,55.7462161],[-1.9697453,55.9190951],[-2.1201694,55.9207115],[-2.1242893,55.9776133],[-2.3440159,55.9783817],[-2.3440159,56.0390349],[-2.5046909,56.0413363],[-2.500571,56.1003588],[-2.8823459,56.0957629],[-2.8823459,56.1722898],[-2.4126804,56.1692316],[-2.4181736,56.2334017],[-2.5857151,56.2303484],[-2.5719822,56.3416356],[-2.7257908,56.3462022],[-2.7312839,56.4343808],[-2.6928318,56.4343808],[-2.6928318,56.4859769],[-2.5307834,56.4935587],[-2.5307834,56.570806],[-2.5302878,56.6047947],[-2.3732428,56.6044452],[-2.3684363,56.7398824],[-2.3292975,56.7398824],[-2.3292975,56.7888065],[-2.3145346,56.7891826],[-2.3148779,56.7967036],[-2.171369,56.7967036],[-2.1703979,56.9710595],[-2.0101725,56.9694716],[-2.0101725,57.0846832],[-2.0817687,57.085349],[-2.0488097,57.1259963],[-2.0409133,57.126369],[-2.0383434,57.2411129],[-1.878118,57.2421638],[-1.8771469,57.2978175],[-1.9868771,57.2983422],[-1.9082209,57.3560063],[-1.8752048,57.3560063],[-1.8761758,57.3769527],[-1.8120857,57.4120111],[-1.7120661,57.4120111],[-1.7034646,57.6441388],[-1.8666032,57.6451781],[-1.8646611,57.7033351],[-3.1204292,57.7064705],[-3.1218025,57.7504652],[-3.4445259,57.7526635],[-3.4472724,57.7138067],[-3.5145637,57.7094052],[-3.5118171,57.6939956],[-3.7645027,57.6917938],[-3.7672492,57.6344975],[-3.842378,57.6288312],[-3.8438346,57.5965825],[-3.9414265,57.5916386],[-3.9404554,57.6537782],[-3.8894746,57.6529989],[-3.8826772,57.7676408],[-3.7224517,57.766087],[-3.7195385,57.8819201],[-3.9146888,57.8853352],[-3.916062,57.9546243],[-3.745774,57.9538956],[-3.7471473,58.0688409],[-3.5837256,58.0695672],[-3.5837256,58.1116689],[-3.4560096,58.1138452],[-3.4544646,58.228503],[-3.4379851,58.2283222],[-3.4243233,58.2427725],[-3.412307,58.2438567],[-3.3735115,58.2695057],[-3.3063919,58.2862038],[-3.1229154,58.2859395],[-3.123602,58.3443661],[-2.9574338,58.3447264],[-2.951254,58.6422011],[-2.8812162,58.6429157],[-2.8851004,58.8112825],[-2.7180775,58.8142997],[-2.7161354,58.8715749],[-2.556881,58.8775984],[-2.5544533,58.9923453],[-2.5567617,59.0483775],[-2.391893,59.0485996],[-2.3918002,59.1106996],[-2.4733695,59.1106996],[-2.5591563,59.1783028],[-2.5630406,59.2210646],[-2.3921334,59.224046],[-2.3911409,59.2740075],[-2.3639512,59.2745036],[-2.3658933,59.285417],[-2.3911409,59.284921],[-2.3911409,59.3379505],[-2.2221759,59.3381981],[-2.2233897,59.395965],[-2.3758467,59.396583],[-2.3899271,59.4026383],[-2.4008516,59.3962122],[-2.5637882,59.3952604],[-2.5637882,59.3385811],[-2.7320164,59.3375306],[-2.7333896,59.3952604],[-3.0726511,59.3931174],[-3.0703404,59.3354759],[-3.0753186,59.3355634],[-3.0749753,59.3292593],[-3.0698254,59.3289091],[-3.069801,59.2196159],[-3.2363384,59.2166341],[-3.2336751,59.1606496],[-3.4032766,59.1588895],[-3.394086,58.9279316],[-3.5664497,58.9259268],[-3.5611089,58.8679885],[-3.392508,58.8699339],[-3.3894734,58.8698711],[-3.3891093,58.8684905],[-3.3912942,58.868616],[-3.3884161,58.7543084],[-3.2238208,58.7555677],[-3.2189655,58.691289],[-3.4634113,58.6905753],[-3.4551716,58.6341518],[-3.787508,58.6341518],[-3.7861347,58.5769211],[-3.9028645,58.5733411],[-3.9028645,58.6477304],[-4.0690327,58.6491594],[-4.0690327,58.5912376],[-4.7364521,58.5933845],[-4.7364521,58.6505884],[-5.0715351,58.6520173],[-5.0654779,58.5325854],[-5.2332047,58.5316087],[-5.2283494,58.4719947],[-5.2424298,58.4719947],[-5.2366034,58.4089731],[-5.2283494,58.4094818],[-5.2210664,58.3005859],[-5.5657939,58.2959933],[-5.5580254,58.2372573],[-5.4146722,58.2401326],[-5.4141866,58.2267768],[-5.3885749,58.2272242],[-5.382714,58.1198615],[-5.51043,58.1191362],[-5.5114011,58.006214],[-5.6745397,58.0041559],[-5.6716266,57.9449366],[-5.6716266,57.8887166],[-5.8347652,57.8856193],[-5.8277052,57.5988958],[-6.0384259,57.5986357],[-6.0389115,57.6459559],[-6.1981658,57.6456961],[-6.2076123,57.7600132],[-6.537067,57.7544033],[-6.5312406,57.6402392],[-6.7002056,57.6360809],[-6.6807844,57.5236293],[-6.8516915,57.5152857],[-6.8361545,57.3385811],[-6.6730158,57.3438213],[-6.674958,57.2850883],[-6.5098772,57.2850883],[-6.4982244,57.1757637],[-6.3506228,57.1820797],[-6.3312015,57.1251969],[-6.1797156,57.1230884],[-6.1719471,57.0682265],[-6.4593819,57.059779],[-6.4564687,57.1093806],[-6.6671895,57.1062165],[-6.6730158,57.002708],[-6.5021087,57.0048233],[-6.4836097,56.8917522],[-6.3266104,56.8894062],[-6.3156645,56.7799312],[-6.2146739,56.775675],[-6.2146739,56.7234965],[-6.6866107,56.7224309],[-6.6769001,56.6114413],[-6.8419809,56.607166],[-6.8400387,56.5483307],[-7.1546633,56.5461895],[-7.1488369,56.4872592],[-6.9915246,56.490476],[-6.9876404,56.4325329],[-6.6827265,56.4314591],[-6.6769001,56.5472601],[-6.5292985,56.5504717],[-6.5234721,56.4379018],[-6.3661598,56.4368281],[-6.3642177,56.3766524],[-6.5273563,56.3712749],[-6.5171745,56.2428427],[-6.4869621,56.247421],[-6.4869621,56.1893882],[-6.3001945,56.1985572],[-6.3029411,56.2581017],[-5.9019401,56.256576],[-5.8964469,56.0960466],[-6.0282829,56.0883855],[-6.0392692,56.1557502],[-6.3853385,56.1542205],[-6.3606193,55.96099],[-6.2123039,55.9640647],[-6.2047508,55.9202269],[-6.5185478,55.9129158],[-6.5061881,55.7501763],[-6.6764762,55.7409005],[-6.6599967,55.6263176],[-6.3551261,55.6232161],[-6.3578727,55.5689002],[-6.0392692,55.5720059],[-6.0310294,55.6247669],[-5.7398917,55.6309694],[-5.7371452,55.4569279],[-5.8964469,55.4600426],[-5.8964469,55.2789864],[-5.4350211,55.2821151],[-5.4405143,55.4506979],[-5.2867057,55.4569279],[-5.3086784,55.4070602],[-4.9735954,55.4008223],[-4.9845817,55.2038242],[-5.1493766,55.2038242],[-5.1411369,55.037337],[-5.2152946,55.0341891],[-5.2112173,54.8018593]],[[-2.1646559,60.1622059],[-1.9930299,60.1609801],[-1.9946862,60.1035151],[-2.1663122,60.104743],[-2.1646559,60.1622059]],[[-1.5360658,59.8570831],[-1.3653566,59.8559841],[-1.366847,59.7975565],[-1.190628,59.7964199],[-1.1862046,59.9695391],[-1.0078652,59.9683948],[-1.0041233,60.114145],[-0.8360832,60.1130715],[-0.834574,60.1716772],[-1.0074262,60.1727795],[-1.0052165,60.2583924],[-0.8299659,60.2572778],[-0.826979,60.3726551],[-0.6507514,60.3715381],[-0.6477198,60.4882292],[-0.9984896,60.4904445],[-0.9970279,60.546555],[-0.6425288,60.5443201],[-0.6394896,60.6606792],[-0.8148133,60.6617806],[-0.8132987,60.7196112],[-0.6383298,60.7185141],[-0.635467,60.8275393],[-0.797568,60.8285523],[-0.9941426,60.8297807],[-0.9954966,60.7782667],[-1.1670282,60.7793403],[-1.1700357,60.6646181],[-1.5222599,60.6668304],[-1.5237866,60.6084426],[-1.6975673,60.609536],[-1.7021271,60.4345249],[-1.5260578,60.4334111],[-1.5275203,60.3770719],[-1.8751127,60.3792746],[-1.8781372,60.2624647],[-1.7019645,60.2613443],[-1.7049134,60.1470532],[-1.528659,60.1459283],[-1.5360658,59.8570831]],[[-0.9847667,60.8943762],[-0.9860347,60.8361105],[-0.8078362,60.8351904],[-0.8065683,60.8934578],[-0.9847667,60.8943762]],[[-7.7696901,56.8788231],[-7.7614504,56.7608274],[-7.6009049,56.7641903],[-7.5972473,56.819332],[-7.4479894,56.8203948],[-7.4489319,56.8794098],[-7.2841369,56.8794098],[-7.2813904,57.0471152],[-7.1303283,57.0515969],[-7.1330749,57.511801],[-6.96828,57.5147514],[-6.9765198,57.6854668],[-6.8062317,57.6913392],[-6.8089782,57.8041985],[-6.6496765,57.8071252],[-6.6441833,57.8612267],[-6.3200866,57.8626878],[-6.3200866,58.1551617],[-6.1607849,58.1522633],[-6.1552917,58.20874],[-5.9850036,58.2101869],[-5.9904968,58.2680163],[-6.1497986,58.2665717],[-6.1415588,58.5557514],[-6.3173401,58.5557514],[-6.3091003,58.4983923],[-6.4876282,58.4955218],[-6.4876282,58.4423768],[-6.6606628,58.4395018],[-6.6469299,58.3819525],[-6.8117248,58.3805125],[-6.8117248,58.3286357],[-6.9792663,58.3286357],[-6.9710266,58.2694608],[-7.1413147,58.2680163],[-7.1403816,58.0358742],[-7.3020636,58.0351031],[-7.3030347,57.9774797],[-7.1379539,57.9777372],[-7.1413526,57.9202792],[-7.1398961,57.8640206],[-7.3020636,57.862471],[-7.298484,57.7442293],[-7.4509193,57.7456951],[-7.4550392,57.6899522],[-7.6186131,57.6906048],[-7.6198341,57.7456951],[-7.7901222,57.7442293],[-7.7873756,57.6855477],[-7.6222332,57.6853817],[-7.6173779,57.5712602],[-7.788285,57.5709998],[-7.7892561,57.512109],[-7.7038025,57.5115874],[-7.6999183,57.4546902],[-7.5367796,57.4552126],[-7.5348375,57.5126306],[-7.4581235,57.5131521],[-7.4552103,57.2824165],[-7.6115515,57.2845158],[-7.6144647,57.2272651],[-7.451326,57.2256881],[-7.451326,57.1103873],[-7.6164068,57.1088053],[-7.603783,56.8792358],[-7.7696901,56.8788231]],[[-1.7106618,59.5626284],[-1.5417509,59.562215],[-1.5423082,59.5037224],[-1.7112191,59.5041365],[-1.7106618,59.5626284]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"id":"NLSC-EMAP5","name":"NLSC General Map with Contour line","type":"tms","template":"http://maps.nlsc.gov.tw/S_Maps/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=EMAP5_OPENDATA&STYLE=_null&TILEMATRIXSET=EPSG:3857&TILEMATRIX=EPSG:3857:{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image/png","description":"The emap from Taiwan National Land Surveying and Mapping Center","scaleExtent":[0,15],"polygon":[[[120.4570579,26.3970586],[120.44256,26.3708009],[120.44713,26.3531513],[120.4673009,26.3405831],[120.4978723,26.3340866],[120.5141036,26.3401594],[120.5341168,26.3641649],[120.5297045,26.3842128],[120.4956661,26.4015754],[120.4570579,26.3970586]],[[119.9007221,25.9858609],[119.8960071,25.9648902],[119.9131301,25.9470399],[119.9503542,25.9278478],[119.9905563,25.9260623],[120.0198392,25.9363284],[120.0277804,25.9557423],[120.0275322,25.9845224],[119.9989937,26.0010288],[119.9404278,26.0028131],[119.9007221,25.9858609]],[[122.089,24.5485],[121.709,23.4541],[121.717,22.698],[121.818,21.95],[121.803,21.8735],[121.759,21.8087],[121.694,21.7653],[120.861,21.5631],[120.815,21.5576],[120.739,21.5728],[120.661,21.6296],[120.202,22.1809],[119.27,23.0542],[119.153,23.2049],[119.128,23.2485],[119.103,23.4],[119.118,23.4765],[119.137,23.512],[119.361,23.8885],[119.406,23.9407],[120.968,25.2284],[121.408,25.4687],[121.989,25.8147],[122.065,25.8299],[122.141,25.8147],[122.216,25.7663],[122.26,25.7015],[122.297,25.48],[122.196,24.9696],[122.089,24.5485]],[[116.6855033,20.8547596],[116.6309071,20.8149565],[116.5941695,20.7600846],[116.5797214,20.6967501],[116.5893056,20.6325865],[116.621766,20.5753367],[116.6731874,20.5319171],[116.7373678,20.5075783],[116.8065659,20.5052653],[116.8724354,20.5252581],[116.9270316,20.5651373],[116.9637692,20.6200797],[116.9782173,20.6834462],[116.9686331,20.7475883],[116.9361727,20.8047732],[116.8847512,20.8481147],[116.8205709,20.872399],[116.7513728,20.8747063],[116.6855033,20.8547596]],[[118.2261504,24.4563345],[118.2936439,24.4538527],[118.2851467,24.4751026],[118.3097372,24.4916821],[118.3767709,24.4729348],[118.4100947,24.5332285],[118.4479031,24.5284069],[118.4746394,24.4599272],[118.512992,24.4315479],[118.5065839,24.4202318],[118.4811625,24.4332439],[118.4610567,24.4089192],[118.426145,24.3970385],[118.3970055,24.4284184],[118.3765564,24.4258395],[118.3397565,24.3814628],[118.3031926,24.3705764],[118.2574234,24.4139213],[118.1381276,24.3724838],[118.1617342,24.4022433],[118.2094226,24.4139604],[118.1895784,24.4352201],[118.2176338,24.430205],[118.2261504,24.4563345]],[[120.2234496,26.30045],[120.2550843,26.3100412],[120.269888,26.3368716],[120.2591889,26.3652192],[120.2292544,26.3784823],[120.1976197,26.3688968],[120.182816,26.3420738],[120.1935151,26.3137205],[120.2234496,26.30045]],[[119.4374461,25.0047541],[119.4342024,24.9886249],[119.4541901,24.9722553],[119.4827444,24.9718376],[119.4898402,24.9937882],[119.4715877,25.0069239],[119.4374461,25.0047541]],[[119.8869914,26.180381],[119.893227,26.1203128],[119.9285109,26.1080224],[119.9779388,26.1223611],[120.0366775,26.151728],[120.1098054,26.2134921],[120.119269,26.2713663],[120.0629175,26.3172592],[119.9923706,26.3164881],[119.9467732,26.2898799],[119.9020362,26.2439761],[119.8869914,26.180381]]],"terms_url":"http://maps.nlsc.gov.tw/","terms_text":"NLSC EMAP 2015"},{"id":"MAPNIK","name":"OpenStreetMap (Standard)","type":"tms","template":"https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","description":"The default OpenStreetMap layer.","scaleExtent":[0,19],"terms_url":"https://openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","default":true},{"id":"osm-gps","name":"OpenStreetMap GPS traces","type":"tms","template":"http://{switch:a,b,c}.gps-tile.openstreetmap.org/lines/{zoom}/{x}/{y}.png","description":"Public GPS traces uploaded to OpenStreetMap.","scaleExtent":[0,20],"terms_url":"http://www.openstreetmap.org/copyright","terms_text":"© OpenStreetMap contributors","terms_html":"<span style='display: inline-block; padding: 0 8px; background-color: rgba(0,0,0,0.5);'><span style='color: #eee;'>GPS Direction:</span> <span style='font-size: 15px; padding-left: 2px; font-weight: bold;'> <span style='color: #0ee;'>&larr;</span> <span style='color: #96f;'>&darr;</span> <span style='color: #6e0;'>&uarr;</span> <span style='color: #f63;'>&rarr;</span> </span></span> © <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap contributors</a>.","overlay":true},{"id":"OS-historic-25k-OSM_Limited","name":"OS 1:25k historic (OSM)","type":"tms","template":"http://ooc.openstreetmap.org/os1/{zoom}/{x}/{y}.jpg","scaleExtent":[6,17],"polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]]},{"id":"OS-New_Popular_Edition-historic","name":"OS New Popular Edition historic","type":"tms","template":"http://ooc.openstreetmap.org/npe/{zoom}/{x}/{y}.png","polygon":[[[-5.8,49.8],[-5.8,55.8],[1.9,55.8],[1.9,49.8],[-5.8,49.8]]]},{"id":"OS-OpenData_Locator","name":"OS OpenData Locator","type":"tms","template":"http://tiles.itoworld.com/os_locator/{zoom}/{x}/{y}.png","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"overlay":true},{"id":"OS-OpenData_StreetView","name":"OS OpenData StreetView","type":"tms","template":"http://os.openstreetmap.org/sv/{zoom}/{x}/{y}.png","scaleExtent":[1,18],"polygon":[[[-5.8292886,50.0229734],[-5.8292886,50.254819],[-5.373356,50.254819],[-5.373356,50.3530588],[-5.1756021,50.3530588],[-5.1756021,50.5925406],[-4.9970743,50.5925406],[-4.9970743,50.6935617],[-4.7965738,50.6935617],[-4.7965738,50.7822112],[-4.6949503,50.7822112],[-4.6949503,50.9607371],[-4.6043131,50.9607371],[-4.6043131,51.0692066],[-4.3792215,51.0692066],[-4.3792215,51.2521782],[-3.9039346,51.2521782],[-3.9039346,51.2916998],[-3.7171671,51.2916998],[-3.7171671,51.2453014],[-3.1486246,51.2453014],[-3.1486246,51.362067],[-3.7446329,51.362067],[-3.7446329,51.4340386],[-3.8297769,51.4340386],[-3.8297769,51.5298246],[-4.0852091,51.5298246],[-4.0852091,51.4939284],[-4.3792215,51.4939284],[-4.3792215,51.5427168],[-5.1444195,51.5427168],[-5.1444195,51.6296003],[-5.7387103,51.6296003],[-5.7387103,51.774037],[-5.5095393,51.774037],[-5.5095393,51.9802596],[-5.198799,51.9802596],[-5.198799,52.0973358],[-4.8880588,52.0973358],[-4.8880588,52.1831557],[-4.4957492,52.1831557],[-4.4957492,52.2925739],[-4.3015365,52.2925739],[-4.3015365,52.3685318],[-4.1811246,52.3685318],[-4.1811246,52.7933685],[-4.4413696,52.7933685],[-4.4413696,52.7369614],[-4.8569847,52.7369614],[-4.8569847,52.9317255],[-4.7288044,52.9317255],[-4.7288044,53.5038599],[-4.1578191,53.5038599],[-4.1578191,53.4113498],[-3.3110518,53.4113498],[-3.3110518,53.5038599],[-3.2333667,53.5038599],[-3.2333667,54.0159169],[-3.3926211,54.0159169],[-3.3926211,54.1980953],[-3.559644,54.1980953],[-3.559644,54.433732],[-3.7188984,54.433732],[-3.7188984,54.721897],[-4.3015365,54.721897],[-4.3015365,54.6140739],[-5.0473132,54.6140739],[-5.0473132,54.7532915],[-5.2298731,54.7532915],[-5.2298731,55.2190799],[-5.6532567,55.2190799],[-5.6532567,55.250088],[-5.8979647,55.250088],[-5.8979647,55.4822462],[-6.5933212,55.4822462],[-6.5933212,56.3013441],[-7.1727691,56.3013441],[-7.1727691,56.5601822],[-6.8171722,56.5601822],[-6.8171722,56.6991713],[-6.5315276,56.6991713],[-6.5315276,56.9066964],[-6.811679,56.9066964],[-6.811679,57.3716613],[-6.8721038,57.3716613],[-6.8721038,57.5518893],[-7.0973235,57.5518893],[-7.0973235,57.2411085],[-7.1742278,57.2411085],[-7.1742278,56.9066964],[-7.3719817,56.9066964],[-7.3719817,56.8075885],[-7.5202972,56.8075885],[-7.5202972,56.7142479],[-7.8306806,56.7142479],[-7.8306806,56.8994605],[-7.6494061,56.8994605],[-7.6494061,57.4739617],[-7.8306806,57.4739617],[-7.8306806,57.7915584],[-7.4736249,57.7915584],[-7.4736249,58.086063],[-7.1879804,58.086063],[-7.1879804,58.367197],[-6.8034589,58.367197],[-6.8034589,58.4155786],[-6.638664,58.4155786],[-6.638664,58.4673277],[-6.5178143,58.4673277],[-6.5178143,58.5625632],[-6.0536224,58.5625632],[-6.0536224,58.1568843],[-6.1470062,58.1568843],[-6.1470062,58.1105865],[-6.2799798,58.1105865],[-6.2799798,57.7122664],[-6.1591302,57.7122664],[-6.1591302,57.6667563],[-5.9339104,57.6667563],[-5.9339104,57.8892524],[-5.80643,57.8892524],[-5.80643,57.9621767],[-5.6141692,57.9621767],[-5.6141692,58.0911236],[-5.490819,58.0911236],[-5.490819,58.3733281],[-5.3199118,58.3733281],[-5.3199118,58.75015],[-3.5719977,58.75015],[-3.5719977,59.2091788],[-3.1944501,59.2091788],[-3.1944501,59.4759216],[-2.243583,59.4759216],[-2.243583,59.1388749],[-2.4611012,59.1388749],[-2.4611012,58.8185938],[-2.7407675,58.8185938],[-2.7407675,58.5804743],[-2.9116746,58.5804743],[-2.9116746,58.1157523],[-3.4865441,58.1157523],[-3.4865441,57.740386],[-1.7153245,57.740386],[-1.7153245,57.2225558],[-1.9794538,57.2225558],[-1.9794538,56.8760742],[-2.1658979,56.8760742],[-2.1658979,56.6333186],[-2.3601106,56.6333186],[-2.3601106,56.0477521],[-1.9794538,56.0477521],[-1.9794538,55.8650949],[-1.4745008,55.8650949],[-1.4745008,55.2499926],[-1.3221997,55.2499926],[-1.3221997,54.8221737],[-1.0550014,54.8221737],[-1.0550014,54.6746628],[-0.6618765,54.6746628],[-0.6618765,54.5527463],[-0.3247617,54.5527463],[-0.3247617,54.2865195],[0.0092841,54.2865195],[0.0092841,53.7938518],[0.2081962,53.7938518],[0.2081962,53.5217726],[0.4163548,53.5217726],[0.4163548,53.0298851],[1.4273388,53.0298851],[1.4273388,52.92021],[1.8333912,52.92021],[1.8333912,52.042488],[1.5235504,52.042488],[1.5235504,51.8261335],[1.2697049,51.8261335],[1.2697049,51.6967453],[1.116651,51.6967453],[1.116651,51.440346],[1.5235504,51.440346],[1.5235504,51.3331831],[1.4507565,51.3331831],[1.4507565,51.0207553],[1.0699883,51.0207553],[1.0699883,50.9008416],[0.7788126,50.9008416],[0.7788126,50.729843],[-0.7255952,50.729843],[-0.7255952,50.7038437],[-1.0074383,50.7038437],[-1.0074383,50.5736307],[-2.3625252,50.5736307],[-2.3625252,50.4846421],[-2.4987805,50.4846421],[-2.4987805,50.5736307],[-3.4096378,50.5736307],[-3.4096378,50.2057837],[-3.6922446,50.2057837],[-3.6922446,50.1347737],[-5.005468,50.1347737],[-5.005468,49.9474456],[-5.2839506,49.9474456],[-5.2839506,50.0229734],[-5.8292886,50.0229734]],[[-6.4580707,49.8673563],[-6.4580707,49.9499935],[-6.3978807,49.9499935],[-6.3978807,50.0053797],[-6.1799606,50.0053797],[-6.1799606,49.9168614],[-6.2540201,49.9168614],[-6.2540201,49.8673563],[-6.4580707,49.8673563]],[[-5.8343165,49.932156],[-5.8343165,49.9754641],[-5.7683254,49.9754641],[-5.7683254,49.932156],[-5.8343165,49.932156]],[[-1.9483797,60.6885737],[-1.9483797,60.3058841],[-1.7543149,60.3058841],[-1.7543149,60.1284428],[-1.5754914,60.1284428],[-1.5754914,59.797917],[-1.0316959,59.797917],[-1.0316959,60.0354518],[-0.6626918,60.0354518],[-0.6626918,60.9103862],[-1.1034395,60.9103862],[-1.1034395,60.8040022],[-1.3506319,60.8040022],[-1.3506319,60.6885737],[-1.9483797,60.6885737]],[[-2.203381,60.1968568],[-2.203381,60.0929443],[-1.9864011,60.0929443],[-1.9864011,60.1968568],[-2.203381,60.1968568]],[[-1.7543149,59.5698289],[-1.7543149,59.4639383],[-1.5373349,59.4639383],[-1.5373349,59.5698289],[-1.7543149,59.5698289]],[[-4.5585981,59.1370518],[-4.5585981,58.9569099],[-4.2867004,58.9569099],[-4.2867004,59.1370518],[-4.5585981,59.1370518]],[[-6.2787732,59.2025744],[-6.2787732,59.0227769],[-5.6650612,59.0227769],[-5.6650612,59.2025744],[-6.2787732,59.2025744]],[[-8.7163482,57.9440556],[-8.7163482,57.7305936],[-8.3592926,57.7305936],[-8.3592926,57.9440556],[-8.7163482,57.9440556]],[[-7.6077005,50.4021026],[-7.6077005,50.2688657],[-7.3907205,50.2688657],[-7.3907205,50.4021026],[-7.6077005,50.4021026]],[[-7.7304303,58.3579902],[-7.7304303,58.248313],[-7.5134503,58.248313],[-7.5134503,58.3579902],[-7.7304303,58.3579902]]]},{"id":"OS-Scottish_Popular-historic","name":"OS Scottish Popular historic","type":"tms","template":"http://ooc.openstreetmap.org/npescotland/tiles/{zoom}/{x}/{y}.jpg","scaleExtent":[6,15],"polygon":[[[-7.8,54.5],[-7.8,61.1],[-1.1,61.1],[-1.1,54.5],[-7.8,54.5]]]},{"id":"Pangasinan_Bulacan_HiRes","name":"Pangasinán/Bulacan (Phillipines HiRes)","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/imagery/philippines/{zoom}/{x}/{y}.png","scaleExtent":[12,19],"polygon":[[[120.336593,15.985768],[120.445995,15.984],[120.446134,15.974459],[120.476464,15.974592],[120.594247,15.946832],[120.598064,16.090795],[120.596537,16.197999],[120.368537,16.218527],[120.347576,16.042308],[120.336593,15.985768]],[[120.8268,15.3658],[121.2684,15.2602],[121.2699,14.7025],[120.695,14.8423],[120.8268,15.3658]]]},{"id":"PNOA-Spain-TMS","name":"PNOA Spain","type":"tms","template":"http://www.ign.es/wmts/pnoa-ma?request=GetTile&service=WMTS&VERSION=1.0.0&Layer=OI.OrthoimageCoverage&Style=default&Format=image/png&TileMatrixSet=GoogleMapsCompatible&TileMatrix={zoom}&TileRow={y}&TileCol={x}","polygon":[[[-17.8846298,28.4460601],[-17.8939535,28.5225529],[-18.0212548,28.7481927],[-18.0224091,28.8038375],[-17.9424017,28.8726124],[-17.8911792,28.8737099],[-17.8903302,28.8515102],[-17.7675902,28.8537764],[-17.7669837,28.8312183],[-17.7412714,28.8319975],[-17.7394926,28.7642235],[-17.7139824,28.7649677],[-17.7129312,28.7303731],[-17.7574427,28.6931782],[-17.7570788,28.6741254],[-17.7457913,28.6743524],[-17.7457266,28.6165627],[-17.7519687,28.5833675],[-17.7622536,28.5591958],[-17.7833086,28.541667],[-17.7831575,28.4936643],[-17.808611,28.4925024],[-17.8060072,28.4468974],[-17.8846298,28.4460601]],[[-18.1661033,27.7851643],[-18.163494,27.6949247],[-18.0889827,27.6963366],[-18.0873398,27.6738724],[-18.0364092,27.6753701],[-18.0350079,27.6302571],[-17.9589987,27.6323976],[-17.8603269,27.7926025],[-17.8630328,27.8368793],[-17.8884015,27.8364947],[-17.8891263,27.8590536],[-17.9906491,27.8567467],[-18.0386803,27.7655831],[-18.1146412,27.7637873],[-18.1154627,27.7863613],[-18.1661033,27.7851643]],[[-17.36038,28.0639801],[-17.3629657,28.1757247],[-17.3375583,28.1763688],[-17.3384577,28.2213012],[-17.1857883,28.2238767],[-17.0820788,28.1351849],[-17.0808422,28.0679977],[-17.1315446,28.0668073],[-17.1563337,28.0214628],[-17.2321063,28.0203711],[-17.2319938,27.9980388],[-17.2576823,27.9978403],[-17.257851,28.0199741],[-17.3086658,28.0192298],[-17.36038,28.0639801]],[[-16.9278171,28.3275779],[-16.9286591,28.3721879],[-16.8776666,28.3729288],[-16.8780707,28.3954191],[-16.5214259,28.4226146],[-16.4457117,28.491135],[-16.4462506,28.535972],[-16.4205859,28.5362679],[-16.4209227,28.5588419],[-16.3443329,28.5597589],[-16.3446023,28.5822095],[-16.1912541,28.5837179],[-16.1916246,28.6068435],[-16.1279344,28.6078193],[-16.1277997,28.5921762],[-16.0995079,28.5925015],[-16.0993395,28.5163822],[-16.1648148,28.5161158],[-16.1647474,28.4938583],[-16.2385755,28.4484704],[-16.2653516,28.4476116],[-16.2658569,28.4030038],[-16.3167484,28.4017594],[-16.3163105,28.380189],[-16.3420763,28.3795075],[-16.3408301,28.2892963],[-16.415837,28.1976134],[-16.415096,28.1311312],[-16.5153297,28.0164796],[-16.6168433,28.01532],[-16.6168096,27.9930469],[-16.7184243,27.9919168],[-16.7190979,28.0371426],[-16.7446952,28.0367859],[-16.7453351,28.0818146],[-16.7706967,28.0816065],[-16.8223966,28.1259036],[-16.8231712,28.1708652],[-16.8487012,28.1707464],[-16.8502842,28.260791],[-16.8756457,28.2605537],[-16.8760836,28.2832162],[-16.9015125,28.2827713],[-16.9023882,28.3279337],[-16.9278171,28.3275779]],[[-15.8537427,27.9008901],[-15.8542032,27.9901812],[-15.828953,27.9906555],[-15.8291065,28.035578],[-15.7782992,28.0363232],[-15.7532793,28.0814298],[-15.7278756,28.0815652],[-15.7282593,28.1718567],[-15.4989741,28.1728039],[-15.4987438,28.1504075],[-15.4497785,28.1507459],[-15.4501622,28.1961425],[-15.3972827,28.1961425],[-15.3964385,28.0383554],[-15.3710348,28.0380167],[-15.3706511,28.0153212],[-15.3457847,28.0153212],[-15.3454777,27.9254406],[-15.3708046,27.9252372],[-15.3705743,27.8352137],[-15.395978,27.8347387],[-15.4209979,27.7879673],[-15.4718052,27.7893932],[-15.471882,27.7666454],[-15.522766,27.7667813],[-15.5477092,27.7216112],[-15.6236132,27.7213395],[-15.6241504,27.741991],[-15.7007451,27.7433495],[-15.801669,27.8110501],[-15.8537427,27.9008901]],[[-14.5215621,28.0467778],[-14.5224358,28.1184131],[-14.4157526,28.1156076],[-14.2168794,28.2278805],[-14.2153651,28.33903],[-14.1641672,28.4528287],[-14.1115132,28.4747955],[-14.0335806,28.7226671],[-13.9565217,28.7449351],[-13.9561722,28.7665857],[-13.8290221,28.7664325],[-13.8289639,28.7879765],[-13.8000741,28.7879255],[-13.8012972,28.7189894],[-13.827566,28.719347],[-13.8278572,28.6517968],[-13.8025786,28.651899],[-13.8033941,28.5384172],[-13.8288474,28.5384684],[-13.8315061,28.3970177],[-13.9158189,28.2241438],[-13.9856445,28.2235696],[-14.0369588,28.1795787],[-14.1387139,28.1799894],[-14.1386556,28.1579103],[-14.2153651,28.1578076],[-14.2147244,28.1118888],[-14.2913173,28.0452356],[-14.3319673,28.0368713],[-14.4457846,28.0469834],[-14.4466583,28.0657961],[-14.4962835,28.0682631],[-14.495934,28.0458525],[-14.5215621,28.0467778]],[[-13.800662,28.8456579],[-13.8009273,28.8231121],[-13.775688,28.8230539],[-13.69729,28.8898184],[-13.69729,28.9127744],[-13.6072498,28.9117991],[-13.4388551,29.0002417],[-13.4374559,29.1351289],[-13.4117005,29.1349931],[-13.4105556,29.2229789],[-13.4592801,29.255586],[-13.4597392,29.2942023],[-13.5091254,29.2945638],[-13.5100581,29.3163453],[-13.5635382,29.3172941],[-13.5640564,29.2713764],[-13.5389228,29.2711956],[-13.5389747,29.2500375],[-13.5661293,29.2501279],[-13.5665956,29.2030039],[-13.5156549,29.2022349],[-13.5156549,29.1820579],[-13.5398038,29.1827819],[-13.5408921,29.137528],[-13.65782,29.1368528],[-13.713222,29.0935079],[-13.7663353,29.0934533],[-13.8502463,29.0165937],[-13.8518224,28.983425],[-13.8524443,28.914861],[-13.9013122,28.89245],[-13.9024005,28.8469779],[-13.800662,28.8456579]],[[1.6479916,38.9990693],[1.7321668,38.9993635],[1.7314703,39.0441733],[1.6489512,39.0431944],[1.6481552,39.1276358],[1.3948608,39.1265691],[1.3954412,39.0864199],[1.2281145,39.0852615],[1.2291095,39.0028958],[1.1448657,39.0018003],[1.1452803,38.8319988],[1.3113632,38.8331615],[1.3121924,38.7906483],[1.3946949,38.7916178],[1.3951924,38.7529597],[1.3112803,38.7519251],[1.3125919,38.6238804],[1.6489036,38.6251112],[1.6480745,38.7111504],[1.58456,38.7101152],[1.5811604,38.7005387],[1.5491544,38.7002798],[1.5197188,38.7092094],[1.50355,38.7253185],[1.4813282,38.9155064],[1.5518906,38.9254411],[1.5667328,38.9566554],[1.6487378,38.9583318],[1.6479916,38.9990693]],[[2.5450749,39.4166673],[2.43933,39.4161122],[2.438714,39.4846853],[2.439022,39.4993424],[2.3122308,39.4993424],[2.3119228,39.5417911],[2.2290722,39.5409994],[2.2283536,39.6260571],[2.3460076,39.6270851],[2.9270445,39.9601558],[3.1456647,39.9600498],[3.1460753,40.0019797],[3.2313899,40.0019797],[3.2312872,39.8329231],[3.1482313,39.8331596],[3.1484366,39.7935717],[3.4814817,39.7931773],[3.4803472,39.5959027],[3.3150618,39.4784606],[3.3146179,39.3785504],[3.0830178,39.2499355],[2.9798608,39.2501482],[2.9790395,39.3334971],[2.7287424,39.3334177],[2.7288451,39.4581361],[2.6456865,39.4577397],[2.6453785,39.4996593],[2.5452802,39.4994216],[2.5450749,39.4166673]],[[3.8120402,40.0434431],[3.729082,40.0437979],[3.7286185,39.9584155],[3.8126633,39.9576011],[3.8122771,39.9164393],[3.9608975,39.9159813],[4.1938142,39.791308],[4.3150279,39.7905799],[4.3159934,39.8329294],[4.3987393,39.8320396],[4.3973664,39.9185834],[4.3158003,39.9193274],[4.3161865,40.0433985],[4.2318959,40.0443594],[4.2324752,40.0847793],[4.1491501,40.086109],[4.1490623,40.1255157],[4.0627981,40.1272166],[4.0624217,40.0849941],[3.8128687,40.085294],[3.8120402,40.0434431]],[[-8.8910646,41.8228891],[-9.1092038,42.5751065],[-9.0365469,42.730656],[-9.0883419,42.7269569],[-9.1466113,42.7750272],[-9.2185488,42.9016271],[-9.2760988,42.8605106],[-9.3099094,42.9311297],[-9.2789763,42.9821991],[-9.3099094,43.0600377],[-9.2523594,43.1041725],[-9.2314975,43.1703151],[-9.1473307,43.210176],[-9.06748,43.1991644],[-9.0336694,43.2426748],[-8.99842,43.2447709],[-8.9998588,43.2955793],[-8.9372732,43.3055265],[-8.92936,43.326986],[-8.8638969,43.3290792],[-8.8761263,43.3740655],[-8.8221732,43.3735426],[-8.785485,43.3191358],[-8.7063538,43.305003],[-8.6099575,43.3296025],[-8.5509688,43.3233227],[-8.5243519,43.3364048],[-8.5250713,43.3646525],[-8.45745,43.3918416],[-8.3610538,43.4111803],[-8.3603344,43.4634161],[-8.3344369,43.5797394],[-8.2776063,43.5708796],[-8.0646713,43.7239184],[-7.9992081,43.7233986],[-7.9171994,43.7826357],[-7.8560525,43.7914643],[-7.83591,43.7374337],[-7.6628443,43.809819],[-7.3188932,43.6782695],[-7.1997467,43.5830817],[-6.2488228,43.6075032],[-6.1229322,43.5790105],[-5.8520425,43.6798953],[-5.6036334,43.5708672],[-5.2855347,43.5619084],[-5.1787525,43.4991591],[-4.9089869,43.4836655],[-4.6156167,43.4192021],[-4.1839917,43.4249168],[-3.8029478,43.5195394],[-3.7400025,43.4869277],[-3.5612827,43.5423572],[-3.1083013,43.3816347],[-2.9385737,43.4624573],[-2.7452417,43.4755094],[-2.3046245,43.3170625],[-1.9854018,43.3563045],[-1.8552841,43.3972545],[-1.769802,43.3964383],[-1.7700492,43.3760501],[-1.7100474,43.3756908],[-1.7113451,43.3312527],[-1.7225915,43.3131806],[-1.6890375,43.3129108],[-1.6881106,43.3341294],[-1.6446695,43.3337248],[-1.6449785,43.3133155],[-1.6029903,43.3129528],[-1.6034352,43.2926624],[-1.5635905,43.2921227],[-1.5630468,43.3133844],[-1.4779905,43.3128355],[-1.3667723,43.2761368],[-1.3568809,43.2381533],[-1.3703692,43.1712972],[-1.4423067,43.0833554],[-1.4198262,43.0603647],[-1.3730668,43.051166],[-1.3640746,43.1115893],[-1.3020285,43.135217],[-1.2354864,43.1332484],[-1.2795481,43.0774443],[-1.1923239,43.0649635],[-1.0061856,43.0077821],[-0.942341,42.9748951],[-0.7562028,42.9821318],[-0.7148387,42.9610774],[-0.6968543,42.9031405],[-0.5511809,42.8220693],[-0.5044215,42.8484456],[-0.4288871,42.8200906],[-0.3164848,42.8655842],[-0.1456332,42.810856],[-0.0314324,42.7124874],[0.1861785,42.7540985],[0.3021777,42.7177729],[0.3642238,42.7428729],[0.4487504,42.7144695],[0.6276949,42.7223973],[0.6411832,42.8576747],[0.7149192,42.882718],[0.9675996,42.8181119],[1.108777,42.7989808],[1.1753192,42.7342872],[1.3632559,42.7415521],[1.4113736,42.7093914],[1.4806054,42.7103407],[1.4813006,42.5010664],[1.6443591,42.5020345],[1.6432777,42.5424539],[1.730407,42.5434214],[1.7316429,42.5011803],[2.0638621,42.5016359],[2.0645572,42.4590247],[2.3969309,42.4599364],[2.3976786,42.4178363],[2.4804823,42.4179732],[2.4809767,42.3759441],[2.6447922,42.3762636],[2.6444832,42.4592447],[2.8113266,42.4596094],[2.8112648,42.5010358],[3.063878,42.5008535],[3.063878,42.4591535],[3.2307832,42.4593359],[3.2304935,42.3764363],[3.3141469,42.3760369],[3.3141243,42.3339864],[3.397855,42.3340435],[3.3973912,42.290094],[3.3138923,42.2908368],[3.3139695,42.2070151],[3.1475896,42.2073012],[3.1475896,42.1260612],[3.2305478,42.1260039],[3.2466753,41.9529359],[3.1945206,41.8558943],[3.060537,41.7647419],[2.7835777,41.6371796],[2.26293,41.4271601],[2.1649151,41.2989297],[1.86008,41.2232228],[1.3763003,41.116273],[1.1793714,41.0464585],[1.0858526,41.048493],[0.758537,40.8195599],[0.9114042,40.733761],[0.8781331,40.6751363],[0.6650182,40.5358666],[0.5580112,40.5502166],[0.433919,40.3757589],[0.2675635,40.1919192],[0.1641534,40.0647234],[0.0751307,40.0144671],[0.010387,39.8952188],[-0.0939224,39.8116904],[-0.1847435,39.6311716],[-0.2908513,39.5036254],[-0.2863552,39.333431],[-0.1856427,39.1774612],[-0.2135185,39.1558487],[-0.1110076,38.9722246],[0.0094878,38.8826835],[0.1218901,38.872183],[0.2342925,38.798636],[0.2558737,38.7264162],[0.0958128,38.6133825],[-0.0022021,38.6070586],[-0.0570544,38.5269073],[-0.2719677,38.4762395],[-0.379874,38.3931234],[-0.3834708,38.3381297],[-0.4509122,38.3310763],[-0.5048654,38.2830943],[-0.4823849,38.1948095],[-0.429331,38.1658287],[-0.4545091,38.148859],[-0.5839966,38.1721913],[-0.6136708,38.1198599],[-0.6370505,37.9612228],[-0.6811123,37.9456238],[-0.7323677,37.8810656],[-0.7215771,37.7830562],[-0.688306,37.7340026],[-0.6641461,37.6231485],[-0.7193941,37.5878413],[-0.9196258,37.5375806],[-1.1107098,37.5164093],[-1.3383246,37.5286671],[-1.4408917,37.3903714],[-1.6766966,37.2765189],[-1.8540816,36.9122889],[-2.0683486,36.6929117],[-2.2158766,36.6619233],[-2.3721861,36.7801753],[-2.6812926,36.6591056],[-2.9201476,36.6675585],[-3.09402,36.712625],[-3.4610839,36.6548788],[-3.7280395,36.6929117],[-4.3743529,36.6633322],[-4.6571151,36.4404171],[-4.9188018,36.4531321],[-5.1699508,36.3513541],[-5.2841094,36.1970201],[-5.2680911,36.1241812],[-5.3524784,36.1224654],[-5.3516094,36.0401413],[-5.4365759,36.0388921],[-5.4353207,36.0034384],[-5.6888562,36.0036518],[-5.6899635,36.0405317],[-5.85506,36.0385595],[-5.8566821,36.1242077],[-5.9384817,36.1221487],[-5.9400265,36.1655625],[-5.9983445,36.1645024],[-6.0357297,36.1780957],[-6.0775178,36.2224132],[-6.1506113,36.2864561],[-6.231541,36.3770075],[-6.3358504,36.5310643],[-6.3214629,36.5816265],[-6.404191,36.6234958],[-6.4743301,36.7489673],[-6.4158808,36.7993866],[-6.490516,36.9173818],[-6.6298949,37.0194012],[-6.8744824,37.1083766],[-7.0426363,37.1850699],[-7.2647434,37.1843535],[-7.3753473,37.1535419],[-7.408316,37.1682196],[-7.4202886,37.2118318],[-7.4249231,37.2350505],[-7.4380543,37.2451969],[-7.4459717,37.3326142],[-7.4480958,37.3909382],[-7.4696271,37.4075829],[-7.4647029,37.4530494],[-7.5019723,37.516411],[-7.5191587,37.5229203],[-7.5219588,37.5723727],[-7.4501271,37.6695835],[-7.4249019,37.7599222],[-7.316662,37.839974],[-7.268329,37.988952],[-7.1536786,38.0155235],[-7.1177098,38.0553626],[-7.0142997,38.0243785],[-6.9963153,38.1075633],[-6.9614706,38.201254],[-7.080617,38.1570753],[-7.3402665,38.4402363],[-7.2638329,38.7380741],[-7.0435243,38.8729667],[-7.0615086,38.907962],[-6.9693387,39.0198308],[-7.0008114,39.0887867],[-7.1536786,39.0957658],[-7.1525545,39.1602899],[-7.2447245,39.1968854],[-7.2559647,39.2813308],[-7.3368944,39.3535074],[-7.3279022,39.4559917],[-7.5144901,39.5886496],[-7.5527069,39.6795427],[-7.0502684,39.6752171],[-6.9951913,39.8195433],[-6.9221297,39.8790868],[-6.886161,40.0229854],[-7.0412762,40.1347927],[-7.0176717,40.266146],[-6.8086034,40.3450071],[-6.8681766,40.4451649],[-6.8535643,40.6066433],[-6.837828,40.8757589],[-6.9536024,41.0370445],[-6.8018592,41.0395879],[-6.7681385,41.138706],[-6.6411239,41.2655616],[-6.5624422,41.2630269],[-6.217367,41.5791017],[-6.3162811,41.644652],[-6.5152332,41.6412921],[-6.5871707,41.6883151],[-6.5478299,41.8559743],[-6.6298836,41.9112057],[-7.1334461,41.9404756],[-7.1682909,41.8718791],[-7.4256922,41.7847727],[-7.9539833,41.8459271],[-8.130455,41.7805819],[-8.2518495,41.9078597],[-8.1293309,42.0348842],[-8.2484774,42.1008034],[-8.3676239,42.0557521],[-8.6070409,42.0340493],[-8.8910646,41.8228891]]],"terms_text":"PNOA","best":true},{"id":"Slovakia-Historic-Maps","name":"Slovakia Historic Maps","type":"tms","template":"http://tms.freemap.sk/historicke/{zoom}/{x}/{y}.png","scaleExtent":[0,12],"polygon":[[[16.8196949,47.4927236],[16.8196949,49.5030322],[22.8388318,49.5030322],[22.8388318,47.4927236],[16.8196949,47.4927236]]]},{"id":"South_Africa-CD_NGI-Aerial","name":"South Africa CD:NGI Aerial","type":"tms","template":"http://{switch:a,b,c}.aerial.openstreetmap.org.za/ngi-aerial/{zoom}/{x}/{y}.jpg","scaleExtent":[1,22],"polygon":[[[17.8396817,-32.7983384],[17.8893509,-32.6972835],[18.00364,-32.6982187],[18.0991679,-32.7485251],[18.2898747,-32.5526645],[18.2930182,-32.0487089],[18.105455,-31.6454966],[17.8529257,-31.3443951],[17.5480046,-30.902171],[17.4044506,-30.6374731],[17.2493704,-30.3991663],[16.9936977,-29.6543552],[16.7987996,-29.19437],[16.5494139,-28.8415949],[16.4498691,-28.691876],[16.4491046,-28.5515766],[16.6002551,-28.4825663],[16.7514057,-28.4486958],[16.7462192,-28.2458973],[16.8855148,-28.04729],[16.9929502,-28.0244005],[17.0529659,-28.0257086],[17.1007562,-28.0338839],[17.2011527,-28.0930546],[17.2026346,-28.2328424],[17.2474611,-28.2338215],[17.2507953,-28.198892],[17.3511919,-28.1975861],[17.3515624,-28.2442655],[17.4015754,-28.2452446],[17.4149122,-28.3489751],[17.4008345,-28.547997],[17.4526999,-28.5489733],[17.4512071,-28.6495106],[17.4983599,-28.6872054],[17.6028204,-28.6830048],[17.6499732,-28.6967928],[17.6525928,-28.7381457],[17.801386,-28.7381457],[17.9994276,-28.7560602],[18.0002748,-28.7956172],[18.1574507,-28.8718055],[18.5063811,-28.8718055],[18.6153564,-28.8295875],[18.9087513,-28.8277516],[19.1046973,-28.9488548],[19.1969071,-28.9378513],[19.243012,-28.8516164],[19.2314858,-28.802963],[19.2587296,-28.7009928],[19.4431493,-28.6973163],[19.5500289,-28.4958332],[19.6967264,-28.4939914],[19.698822,-28.4479358],[19.8507587,-28.4433291],[19.8497109,-28.4027818],[19.9953605,-28.399095],[19.9893671,-24.7497859],[20.2916682,-24.9192346],[20.4724562,-25.1501701],[20.6532441,-25.4529449],[20.733265,-25.6801957],[20.8281046,-25.8963498],[20.8429232,-26.215851],[20.6502804,-26.4840868],[20.6532441,-26.8204869],[21.0889134,-26.846933],[21.6727695,-26.8389998],[21.7765003,-26.6696268],[21.9721069,-26.6431395],[22.2803355,-26.3274702],[22.5707817,-26.1333967],[22.7752795,-25.6775246],[23.0005235,-25.2761948],[23.4658301,-25.2735148],[23.883717,-25.597366],[24.2364017,-25.613402],[24.603905,-25.7896563],[25.110704,-25.7389432],[25.5078447,-25.6855376],[25.6441766,-25.4823781],[25.8419267,-24.7805437],[25.846641,-24.7538456],[26.3928487,-24.6332894],[26.4739066,-24.5653312],[26.5089966,-24.4842437],[26.5861946,-24.4075775],[26.7300635,-24.3014458],[26.8567384,-24.2499463],[26.8574402,-24.1026901],[26.9215471,-23.8990957],[26.931831,-23.8461891],[26.9714827,-23.6994344],[27.0006074,-23.6367644],[27.0578041,-23.6052574],[27.1360547,-23.5203437],[27.3339623,-23.3973792],[27.5144057,-23.3593929],[27.5958145,-23.2085465],[27.8098634,-23.0994957],[27.8828506,-23.0620496],[27.9382928,-22.9496487],[28.0407556,-22.8255118],[28.2056786,-22.6552861],[28.3397223,-22.5639374],[28.4906093,-22.560697],[28.6108769,-22.5400248],[28.828175,-22.4550173],[28.9285324,-22.4232328],[28.9594116,-22.3090081],[29.0162574,-22.208335],[29.2324117,-22.1693453],[29.3531213,-22.1842926],[29.6548952,-22.1186426],[29.7777102,-22.1361956],[29.9292989,-22.1849425],[30.1166795,-22.2830348],[30.2563377,-22.2914767],[30.3033582,-22.3395204],[30.5061784,-22.3057617],[30.8374279,-22.284983],[31.0058599,-22.3077095],[31.1834152,-22.3232913],[31.2930586,-22.3674647],[31.5680579,-23.1903385],[31.5568311,-23.4430809],[31.6931122,-23.6175209],[31.7119696,-23.741136],[31.7774743,-23.8800628],[31.8886337,-23.9481098],[31.9144386,-24.1746736],[31.9948307,-24.3040878],[32.0166656,-24.4405988],[32.0077331,-24.6536578],[32.019643,-24.9140701],[32.035523,-25.0849767],[32.019643,-25.3821442],[31.9928457,-25.4493771],[31.9997931,-25.5165725],[32.0057481,-25.6078978],[32.0057481,-25.6624806],[31.9362735,-25.8403721],[31.9809357,-25.9546537],[31.8687838,-26.0037251],[31.4162062,-25.7277683],[31.3229117,-25.7438611],[31.2504595,-25.8296526],[31.1393001,-25.9162746],[31.1164727,-25.9912361],[30.9656135,-26.2665756],[30.8921689,-26.3279703],[30.8534616,-26.4035568],[30.8226943,-26.4488849],[30.8022583,-26.5240694],[30.8038369,-26.8082089],[30.9020939,-26.7807451],[30.9100338,-26.8489495],[30.9824859,-26.9082627],[30.976531,-27.0029222],[31.0034434,-27.0441587],[31.1543322,-27.1980416],[31.5015607,-27.311117],[31.9700183,-27.311117],[31.9700183,-27.120472],[31.9769658,-27.050664],[32.0002464,-26.7983892],[32.1069826,-26.7984645],[32.3114546,-26.8479493],[32.899986,-26.8516059],[32.886091,-26.9816971],[32.709427,-27.4785436],[32.6240724,-27.7775144],[32.5813951,-28.07479],[32.5387178,-28.2288046],[32.4275584,-28.5021568],[32.3640388,-28.5945699],[32.0702603,-28.8469827],[31.9878832,-28.9069497],[31.7764818,-28.969487],[31.4638459,-29.2859343],[31.359634,-29.3854348],[31.1680825,-29.6307408],[31.064863,-29.7893535],[31.0534493,-29.8470469],[31.0669933,-29.8640319],[31.0455459,-29.9502017],[30.9518556,-30.0033946],[30.8651833,-30.1024093],[30.7244725,-30.392502],[30.3556256,-30.9308873],[30.0972364,-31.2458274],[29.8673136,-31.4304296],[29.7409393,-31.5014699],[29.481312,-31.6978686],[28.8943171,-32.2898903],[28.5497137,-32.5894641],[28.1436499,-32.8320732],[28.0748735,-32.941689],[27.8450942,-33.082869],[27.3757956,-33.3860685],[26.8805407,-33.6458951],[26.5916871,-33.7480756],[26.4527308,-33.7935795],[26.206754,-33.7548943],[26.0077897,-33.7223961],[25.8055494,-33.7524272],[25.7511073,-33.8006512],[25.6529079,-33.8543597],[25.6529079,-33.9469768],[25.7195789,-34.0040115],[25.7202807,-34.0511235],[25.5508915,-34.063151],[25.3504571,-34.0502627],[25.2810609,-34.0020322],[25.0476316,-33.9994588],[24.954724,-34.0043594],[24.9496586,-34.1010363],[24.8770358,-34.1506456],[24.8762914,-34.2005281],[24.8532574,-34.2189562],[24.7645287,-34.2017946],[24.5001356,-34.2003254],[24.3486733,-34.1163824],[24.1988819,-34.1019039],[23.9963377,-34.0514443],[23.8017509,-34.0524332],[23.7493589,-34.0111855],[23.4973536,-34.009014],[23.4155191,-34.0434586],[23.4154284,-34.1140433],[22.9000853,-34.0993009],[22.8412418,-34.0547911],[22.6470321,-34.0502627],[22.6459843,-34.0072768],[22.570016,-34.0064081],[22.5050499,-34.0645866],[22.2519968,-34.0645866],[22.2221334,-34.1014701],[22.1621197,-34.1057019],[22.1712431,-34.1521766],[22.1576913,-34.2180897],[22.0015632,-34.2172232],[21.9496952,-34.3220009],[21.8611528,-34.4007145],[21.5614708,-34.4020114],[21.5468011,-34.3661242],[21.501744,-34.3669892],[21.5006961,-34.4020114],[21.4194886,-34.4465247],[21.1978706,-34.4478208],[21.0988193,-34.3991325],[21.0033746,-34.3753872],[20.893192,-34.3997115],[20.8976647,-34.4854003],[20.7446802,-34.4828092],[20.5042011,-34.486264],[20.2527197,-34.701477],[20.0803502,-34.8361855],[19.9923317,-34.8379056],[19.899074,-34.8275845],[19.8938348,-34.7936018],[19.5972963,-34.7961833],[19.3929677,-34.642015],[19.2877095,-34.6404784],[19.2861377,-34.5986563],[19.3474363,-34.5244458],[19.3285256,-34.4534372],[19.098001,-34.449981],[19.0725583,-34.3802371],[19.0023531,-34.3525593],[18.9520568,-34.3949373],[18.7975006,-34.3936403],[18.7984174,-34.1016376],[18.501748,-34.1015292],[18.4999545,-34.3616945],[18.4477325,-34.3620007],[18.4479944,-34.3522691],[18.3974362,-34.3514041],[18.3971742,-34.3022959],[18.3565705,-34.3005647],[18.3479258,-34.2020436],[18.2972095,-34.1950274],[18.2951139,-33.9937138],[18.3374474,-33.9914079],[18.3476638,-33.8492427],[18.3479258,-33.781555],[18.4124718,-33.7448849],[18.3615477,-33.6501624],[18.2992013,-33.585591],[18.2166839,-33.448872],[18.1389858,-33.3974083],[17.9473472,-33.1602647],[17.8855247,-33.0575732],[17.8485884,-32.9668505],[17.8396817,-32.8507302],[17.8396817,-32.7983384]]],"best":true},{"id":"South-Tyrol-Orthofoto2011","name":"South Tyrol Orthofoto 2011","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2011_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Orthophoto of South Tyrol from 2011","scaleExtent":[0,18],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0"},{"id":"South-Tyrol-Orthofoto2014","name":"South Tyrol Orthofoto 2014","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2014_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Orthophoto of South Tyrol from 2011","scaleExtent":[0,18],"polygon":[[[12.23442,46.84254],[12.24913,46.82785],[12.24913,46.81945],[12.25753,46.81735],[12.26173,46.80686],[12.26594,46.80686],[12.26804,46.79637],[12.26173,46.79427],[12.27014,46.78587],[12.27224,46.76908],[12.28485,46.76698],[12.29745,46.7439],[12.30166,46.7439],[12.30166,46.7376],[12.28695,46.7376],[12.23652,46.72081],[12.18819,46.71451],[12.16298,46.70192],[12.10835,46.69353],[12.08944,46.68303],[12.05792,46.68093],[12.04531,46.67464],[12.03481,46.67464],[12.03061,46.68303],[12.0096,46.68303],[11.98438,46.66834],[11.94866,46.66414],[11.93816,46.65575],[11.90874,46.64525],[11.89193,46.64525],[11.8457,46.62846],[11.82049,46.62636],[11.80998,46.60748],[11.79528,46.60328],[11.78897,46.59069],[11.78057,46.58859],[11.76586,46.55501],[11.75325,46.54871],[11.73855,46.52982],[11.73224,46.52982],[11.72384,46.51513],[11.71543,46.51513],[11.71333,46.50254],[11.70913,46.50254],[11.70913,46.49624],[11.69652,46.48575],[11.69442,46.47735],[11.66711,46.47525],[11.66711,46.44587],[11.6608,46.44587],[11.64399,46.45846],[11.63769,46.45846],[11.63349,46.44587],[11.62508,46.44797],[11.62508,46.43957],[11.61878,46.43957],[11.61458,46.42278],[11.61037,46.42278],[11.61037,46.41649],[11.62508,46.41229],[11.62508,46.3934],[11.61458,46.38291],[11.60617,46.38291],[11.60407,46.37241],[11.58306,46.37241],[11.58306,46.34932],[11.55995,46.32414],[11.53894,46.32834],[11.53894,46.34513],[11.52423,46.34723],[11.50111,46.34723],[11.49901,46.32834],[11.48851,46.33044],[11.49271,46.32204],[11.41917,46.32414],[11.41707,46.25278],[11.35613,46.24858],[11.34773,46.25698],[11.34563,46.26747],[11.34143,46.26747],[11.33722,46.25068],[11.31201,46.24858],[11.30991,46.25278],[11.3015,46.25278],[11.2889,46.24019],[11.2889,46.2234],[11.25108,46.2234],[11.24898,46.2129],[11.16283,46.215],[11.16283,46.24858],[11.12711,46.24858],[11.13131,46.25278],[11.12291,46.25488],[11.12501,46.29895],[11.16283,46.29895],[11.16283,46.36821],[11.16703,46.36821],[11.16703,46.38081],[11.17543,46.3871],[11.17754,46.3997],[11.20485,46.3997],[11.20695,46.42068],[11.19014,46.42068],[11.19014,46.42698],[11.19435,46.42698],[11.19855,46.44167],[11.20485,46.44587],[11.20695,46.47315],[11.19014,46.47525],[11.18804,46.48365],[11.15232,46.47525],[11.08298,46.47525],[11.08088,46.43537],[11.04096,46.42068],[11.01154,46.42068],[10.99894,46.44587],[10.98843,46.44587],[10.98423,46.45217],[10.96952,46.45217],[10.96112,46.48365],[10.95691,46.48365],[10.95481,46.49414],[10.94851,46.49624],[10.94431,46.50673],[10.91069,46.49624],[10.90018,46.49624],[10.89808,46.51093],[10.85606,46.50254],[10.84135,46.54241],[10.86446,46.54661],[10.86236,46.55081],[10.76571,46.54031],[10.72158,46.55081],[10.59762,46.55291],[10.5619,46.54871],[10.53668,46.55291],[10.50096,46.54871],[10.48415,46.55501],[10.46314,46.55501],[10.47155,46.5676],[10.47365,46.59069],[10.47785,46.59069],[10.47785,46.61797],[10.46944,46.62636],[10.44843,46.63476],[10.42532,46.62846],[10.3938,46.63056],[10.3896,46.64525],[10.3812,46.64735],[10.3833,46.66414],[10.3791,46.66834],[10.3791,46.69353],[10.3854,46.72081],[10.3896,46.72081],[10.3938,46.7376],[10.41692,46.75229],[10.41692,46.78587],[10.42112,46.79847],[10.42532,46.79847],[10.42532,46.80686],[10.43373,46.81106],[10.43793,46.79007],[10.44423,46.78377],[10.44843,46.7439],[10.45264,46.7439],[10.45684,46.72711],[10.46104,46.72711],[10.46524,46.71032],[10.46944,46.71032],[10.47365,46.67254],[10.47995,46.67044],[10.48415,46.65575],[10.48836,46.65575],[10.48415,46.62846],[10.48836,46.62846],[10.48836,46.62217],[10.49886,46.62007],[10.52828,46.62427],[10.49886,46.63056],[10.49886,46.64525],[10.50516,46.64316],[10.49886,46.66204],[10.51777,46.65785],[10.58921,46.66204],[10.63123,46.65365],[10.79302,46.65575],[10.79723,46.65155],[10.88127,46.65155],[10.89178,46.65785],[10.9275,46.66414],[10.94431,46.67464],[10.98003,46.67464],[11.00104,46.68303],[11.02415,46.68303],[11.05147,46.69772],[11.12711,46.70822],[11.13971,46.71242],[11.14392,46.71871],[11.17543,46.72081],[11.19855,46.7334],[11.24898,46.7355],[11.25318,46.72291],[11.2952,46.72921],[11.30571,46.70822],[11.31831,46.70822],[11.33722,46.71871],[11.38555,46.72081],[11.43178,46.7376],[11.50952,46.7439],[11.54734,46.75649],[11.56835,46.75649],[11.58306,46.76698],[11.60617,46.76908],[11.61037,46.77538],[11.69862,46.79427],[11.71753,46.79427],[11.72174,46.79007],[11.73855,46.75859],[11.74905,46.75019],[11.76166,46.70192],[11.76586,46.70192],[11.78687,46.71661],[11.8331,46.72291],[11.86041,46.7376],[11.90874,46.7439],[11.92135,46.75229],[11.95286,46.75859],[11.95917,46.76488],[11.99489,46.77538],[12.00749,46.77538],[12.0096,46.77958],[12.03061,46.78168],[12.05792,46.79427],[12.09995,46.79847],[12.13566,46.81316],[12.15878,46.81316],[12.18609,46.82785],[12.21551,46.83205],[12.23442,46.84254]],[[11.97388,46.96637],[11.99489,46.96007],[11.99489,46.95587],[12.0096,46.95797],[12.0117,46.94748],[12.0159,46.94748],[12.0117,46.94118],[12.018,46.93908],[12.02851,46.92229],[12.00749,46.9118],[11.97388,46.9055],[11.95707,46.89501],[11.91714,46.88871],[11.85831,46.86982],[11.8394,46.86982],[11.80158,46.85303],[11.76166,46.84464],[11.74905,46.83415],[11.68181,46.81945],[11.67971,46.81526],[11.6545,46.81106],[11.64399,46.80476],[11.63769,46.80686],[11.63139,46.82155],[11.62508,46.82155],[11.62298,46.83205],[11.61037,46.84464],[11.61668,46.84884],[11.61458,46.85723],[11.61037,46.85723],[11.61668,46.86563],[11.64609,46.86563],[11.68602,46.88242],[11.69022,46.88871],[11.74905,46.89711],[11.75325,46.90341],[11.78057,46.9076],[11.80158,46.9202],[11.8457,46.92649],[11.87722,46.94118],[11.89613,46.94328],[11.92135,46.95797],[11.96757,46.96217],[11.97388,46.96637]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0","best":true},{"id":"South-Tyrol-Topomap","name":"South Tyrol Topomap","type":"tms","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_BASEMAP_TOPO&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Topographical basemap of South Tyrol","scaleExtent":[0,20],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano"},{"id":"Bern-bern2016-tms","name":"Stadt Bern 10cm (2016)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/bern2016/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[7.2943145,46.9237564],[7.2982665,46.9274715],[7.3061586,46.9309487],[7.3043338,46.9362344],[7.3068603,46.9403709],[7.3246431,46.9432765],[7.3284525,46.946409],[7.3414051,46.9460797],[7.3438454,46.9473713],[7.3434554,46.9487937],[7.3513567,46.9485481],[7.3505628,46.950213],[7.3530901,46.9519266],[7.3582028,46.9511773],[7.3685031,46.9566244],[7.3715097,46.9607339],[7.37503,46.959835],[7.3785111,46.9614686],[7.3806232,46.9654741],[7.3832097,46.9663014],[7.3937998,46.9669268],[7.4000528,46.9691779],[7.4082922,46.9686857],[7.4281713,46.9738041],[7.4327053,46.972689],[7.4353602,46.9684345],[7.4378522,46.9684302],[7.4412474,46.9767865],[7.4456893,46.9747939],[7.4483835,46.9756393],[7.4477006,46.9790125],[7.4440468,46.9780682],[7.4412738,46.9798224],[7.4506732,46.9901527],[7.4522112,46.9896803],[7.454649,46.9778182],[7.4680382,46.9758258],[7.4707923,46.969998],[7.4701907,46.9674116],[7.4781618,46.9711823],[7.4845237,46.9701571],[7.4861275,46.9679018],[7.4857945,46.9646828],[7.4784708,46.9629043],[7.4802865,46.9606768],[7.4789304,46.9587841],[7.4797786,46.9566019],[7.4770135,46.9544586],[7.4840504,46.9499938],[7.4833925,46.9451977],[7.4955563,46.9396169],[7.4935119,46.9376594],[7.4908036,46.9387617],[7.4894997,46.9368667],[7.4766667,46.9369496],[7.4781093,46.9362489],[7.4746986,46.9339187],[7.4753537,46.9329898],[7.4691047,46.9292427],[7.4707683,46.9255044],[7.4585674,46.934836],[7.4476373,46.9304297],[7.435418,46.9349668],[7.4338022,46.9331237],[7.4376403,46.9307415],[7.4146941,46.9368183],[7.413844,46.9315682],[7.4070798,46.9303824],[7.408065,46.9256296],[7.4021268,46.9241992],[7.4014835,46.9211927],[7.3875736,46.9304506],[7.3823129,46.927282],[7.3800187,46.9298929],[7.3808694,46.9324085],[7.3748669,46.9314306],[7.3748901,46.9327104],[7.368066,46.9323929],[7.3683058,46.930426],[7.3604074,46.9285884],[7.3605592,46.9272018],[7.338783,46.9245357],[7.3393683,46.9196675],[7.3274574,46.9190326],[7.3269178,46.9235974],[7.324374,46.9251891],[7.3082264,46.9222857],[7.2943145,46.9237564]]],"terms_text":"Orthophoto 2016, Vermessungsamt Stadt Bern ","best":true},{"id":"Uster-2008","name":"Stadt Uster Orthophoto 2008 10cm","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/uster/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.6,47.31],[8.6,47.39],[8.77,47.39],[8.77,47.31],[8.6,47.31]]],"terms_text":"Stadt Uster Vermessung Orthophoto 2008"},{"id":"Zuerich-zh_luftbild2011-tms","name":"Stadt Zürich Luftbild 2011","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_luftbild2011/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4441,47.3141],[8.4441,47.4411],[8.6284,47.4411],[8.6284,47.3141],[8.4441,47.3141]]],"terms_text":"Stadt Zürich Luftbild 2011"},{"id":"Zuerich-city_map","name":"Stadtplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_stadtplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"id":"stamen-terrain-background","name":"Stamen Terrain","type":"tms","template":"http://{switch:a,b,c,d}.tile.stamen.com/terrain-background/{zoom}/{x}/{y}.jpg","scaleExtent":[4,18],"terms_url":"http://maps.stamen.com/#terrain","terms_text":"Map tiles by Stamen Design, under CC BY 3.0"},{"id":"Stevns_Denmark","name":"Stevns (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/stevns/2009/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[12.0913942,55.3491574],[12.0943104,55.3842256],[12.1573875,55.3833103],[12.1587287,55.4013326],[12.1903468,55.400558],[12.1931411,55.4364665],[12.2564251,55.4347995],[12.2547073,55.4168882],[12.3822489,55.4134349],[12.3795942,55.3954143],[12.4109213,55.3946958],[12.409403,55.3766417],[12.4407807,55.375779],[12.4394142,55.3578314],[12.4707413,55.3569971],[12.4629475,55.2672214],[12.4315633,55.2681491],[12.430045,55.2502103],[12.3672011,55.2519673],[12.3656858,55.2340267],[12.2714604,55.2366031],[12.2744467,55.272476],[12.2115654,55.2741475],[12.2130078,55.2920322],[12.1815665,55.2928638],[12.183141,55.3107091],[12.2144897,55.3100981],[12.2159927,55.3279764],[12.1214458,55.3303379],[12.1229489,55.3483291],[12.0913942,55.3491574]]],"terms_text":"Stevns Kommune"},{"id":"Surrey-Air_Survey","name":"Surrey Air Survey","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/surrey/{zoom}/{x}/{y}.png","scaleExtent":[8,19],"polygon":[[[-0.752478,51.0821941],[-0.7595183,51.0856254],[-0.8014342,51.1457917],[-0.8398864,51.1440686],[-0.8357665,51.1802397],[-0.8529549,51.2011266],[-0.8522683,51.2096231],[-0.8495217,51.217903],[-0.8266907,51.2403696],[-0.8120995,51.2469248],[-0.7736474,51.2459577],[-0.7544213,51.2381127],[-0.754078,51.233921],[-0.7446366,51.2333836],[-0.7430693,51.2847178],[-0.751503,51.3069524],[-0.7664376,51.3121032],[-0.7820588,51.3270157],[-0.7815438,51.3388135],[-0.7374268,51.3720456],[-0.7192307,51.3769748],[-0.6795769,51.3847961],[-0.6807786,51.3901523],[-0.6531411,51.3917591],[-0.6301385,51.3905808],[-0.6291085,51.3970074],[-0.6234437,51.3977572],[-0.613144,51.4295552],[-0.6002471,51.4459121],[-0.5867081,51.4445365],[-0.5762368,51.453202],[-0.5626755,51.4523462],[-0.547741,51.4469972],[-0.5372697,51.4448575],[-0.537098,51.4526671],[-0.5439644,51.4545926],[-0.5405312,51.4698865],[-0.5309182,51.4760881],[-0.5091172,51.4744843],[-0.5086022,51.4695657],[-0.4900628,51.4682825],[-0.4526406,51.4606894],[-0.4486924,51.4429316],[-0.4414826,51.4418616],[-0.4418259,51.4369394],[-0.4112702,51.4380095],[-0.4014855,51.4279498],[-0.3807145,51.4262372],[-0.3805428,51.4161749],[-0.3491288,51.4138195],[-0.3274994,51.4037544],[-0.3039818,51.3990424],[-0.3019219,51.3754747],[-0.309475,51.369688],[-0.3111916,51.3529669],[-0.2955704,51.3541462],[-0.2923089,51.3673303],[-0.2850991,51.3680805],[-0.2787476,51.3771891],[-0.2655297,51.3837247],[-0.2411538,51.3847961],[-0.2123147,51.3628288],[-0.2107697,51.3498578],[-0.190857,51.3502867],[-0.1542931,51.3338802],[-0.1496583,51.3057719],[-0.1074296,51.2966491],[-0.0887185,51.3099571],[-0.0878602,51.3220811],[-0.0652009,51.3215448],[-0.0641709,51.3264793],[-0.0519829,51.3263721],[-0.0528412,51.334631],[-0.0330779,51.3430876],[0.0019187,51.3376339],[0.0118751,51.3281956],[0.013935,51.2994398],[0.0202865,51.2994398],[0.0240631,51.3072743],[0.0331611,51.3086694],[0.0455207,51.30545],[0.0523872,51.2877392],[0.0616569,51.2577764],[0.0640602,51.2415518],[0.0462074,51.2126342],[0.0407142,51.2109136],[0.0448341,51.1989753],[0.0494689,51.1997283],[0.0558204,51.1944573],[0.0611419,51.1790713],[0.0623435,51.1542061],[0.0577087,51.1417146],[0.0204582,51.1365447],[-0.0446015,51.1336364],[-0.1566964,51.1352522],[-0.1572114,51.1290043],[-0.2287942,51.1183379],[-0.2473336,51.1183379],[-0.2500802,51.1211394],[-0.299347,51.1137042],[-0.3221779,51.1119799],[-0.3223496,51.1058367],[-0.3596001,51.1019563],[-0.3589135,51.1113333],[-0.3863793,51.1117644],[-0.3869014,51.1062516],[-0.4281001,51.0947174],[-0.4856784,51.0951554],[-0.487135,51.0872266],[-0.5297404,51.0865404],[-0.5302259,51.0789914],[-0.61046,51.076551],[-0.6099745,51.080669],[-0.6577994,51.0792202],[-0.6582849,51.0743394],[-0.6836539,51.0707547],[-0.6997979,51.070831],[-0.7296581,51.0744919],[-0.752478,51.0821941]]]},{"id":"Szeged_2011","name":"Szeged ortophoto 2011","type":"tms","template":"http://e.tile.openstreetmap.hu/szeged-2011-10cm/{zoom}/{x}/{y}.png","scaleExtent":[10,22],"polygon":[[[20.1459914,46.2281144],[20.1332261,46.2290431],[20.1258373,46.2298686],[20.122329,46.2309893],[20.1208484,46.2317537],[20.1189709,46.2335126],[20.1131237,46.2413638],[20.1120293,46.2433005],[20.1115733,46.2449996],[20.1111871,46.247092],[20.1112944,46.2487725],[20.1115948,46.2509686],[20.1122171,46.2528047],[20.1129949,46.2542681],[20.1135421,46.2553549],[20.1147705,46.2567977],[20.1352251,46.2768529],[20.1366386,46.2775055],[20.1378939,46.2780301],[20.1393932,46.2783508],[20.1408818,46.2784583],[20.1611494,46.278159],[20.1621093,46.2781579],[20.1635894,46.277702],[20.1661777,46.2761484],[20.1687795,46.2738569],[20.1696108,46.2714413],[20.1695895,46.2704465],[20.1700871,46.2704418],[20.1739897,46.2643295],[20.1766182,46.2582878],[20.1947983,46.25492],[20.1858719,46.2448077],[20.1846595,46.2453122],[20.1780371,46.2383112],[20.1781766,46.2377101],[20.1795258,46.2370961],[20.1725666,46.2300241],[20.1698349,46.2350404],[20.1687701,46.2362946],[20.1670262,46.2378475],[20.1659431,46.2387342],[20.1654408,46.2389988],[20.1654837,46.2389988],[20.1635177,46.2401383],[20.1602051,46.2412003],[20.1592684,46.241531],[20.1592684,46.2415751],[20.1583504,46.2418505],[20.1549473,46.2422869],[20.1510796,46.2351538],[20.1493804,46.232459],[20.1459914,46.2281144]]],"terms_url":"http://www.geo.u-szeged.hu/","terms_text":"SZTE TFGT - University of Szeged"},{"id":"tnris.org","name":"Texas Orthophoto","type":"tms","template":"https://txgi.tnris.org/login/path/ecology-fiona-poem-romeo/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=texas&STYLE=&FORMAT=image/png&tileMatrixSet=0to20&tileMatrix=0to20:{zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,20],"polygon":[[[-99.9985439,34.5601834],[-95.55654502453,33.99257450647],[-93.89679027134,33.61039304449],[-93.98468089634,32.04103124103],[-93.41613841587,31.02505269211],[-93.74531484297,29.57268254375],[-96.50492070332,28.23158511753],[-97.36942054453,26.95467452634],[-97.04866958924,25.80530249434],[-99.0734177889,26.32559221139],[-100.76599193149,29.02531904433],[-102.3315436893,29.8433892263],[-103.13354564242,28.88112103669],[-104.2887874222,29.28831477845],[-104.7269783935,29.94815782859],[-104.72696778796,30.23535241761],[-106.53450082091,31.78456647831],[-106.75767043939,31.78457253947],[-106.75766067978,32.04385536686],[-106.61848436611,32.04385159755],[-103.11949492759,32.04375683439],[-103.09544343487,36.50045758762],[-103.05798056071,36.54268645422],[-100.00042146824,36.54222227302],[-99.9985439,34.5601834]]],"terms_url":"https://tnris.org/maps-and-data/online-mapping-services/"},{"id":"tf-landscape","name":"Thunderforest Landscape","type":"tms","template":"https://{switch:a,b,c}.tile.thunderforest.com/landscape/{zoom}/{x}/{y}.png","scaleExtent":[0,22],"terms_url":"http://www.thunderforest.com/terms/","terms_text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},{"id":"Toulouse-Orthophotoplan-2007","name":"Toulouse - Orthophotoplan 2007","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2007/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1919978,43.6328791],[1.2015377,43.6329729],[1.2011107,43.6554932],[1.2227985,43.6557029],[1.2226231,43.6653353],[1.2275341,43.6653849],[1.2275417,43.6656387],[1.2337568,43.6656883],[1.2337644,43.6650153],[1.2351218,43.6650319],[1.2350913,43.6670729],[1.2443566,43.6671556],[1.2441584,43.6743925],[1.2493973,43.6744256],[1.2493973,43.6746628],[1.2555666,43.6747234],[1.2555742,43.6744532],[1.2569545,43.6744697],[1.2568782,43.678529],[1.2874873,43.6788257],[1.2870803,43.7013229],[1.3088219,43.7014632],[1.3086493,43.7127673],[1.3303262,43.7129544],[1.3300242,43.7305221],[1.3367106,43.7305845],[1.3367322,43.7312235],[1.3734338,43.7310456],[1.3735848,43.7245772],[1.4604504,43.7252947],[1.4607783,43.7028034],[1.4824875,43.7029516],[1.4829828,43.6692071],[1.5046832,43.6693616],[1.5048383,43.6581174],[1.5265475,43.6582656],[1.5266945,43.6470298],[1.548368,43.6471633],[1.5485357,43.6359385],[1.5702172,43.636082],[1.5705123,43.6135777],[1.5488166,43.6134276],[1.549097,43.5909479],[1.5707695,43.5910694],[1.5709373,43.5798341],[1.5793714,43.5798894],[1.5794782,43.5737682],[1.5809119,43.5737792],[1.5810859,43.5573794],[1.5712334,43.5573131],[1.5716504,43.5235497],[1.3984804,43.5222618],[1.3986509,43.5110113],[1.3120959,43.5102543],[1.3118968,43.5215192],[1.2902569,43.5213126],[1.2898637,43.5438168],[1.311517,43.5440133],[1.3113271,43.5552596],[1.3036924,43.5551924],[1.3036117,43.5595099],[1.2955449,43.5594317],[1.2955449,43.5595489],[1.2895595,43.5594473],[1.2892899,43.5775366],[1.2675698,43.5773647],[1.2673973,43.5886141],[1.25355,43.5885047],[1.2533774,43.5956282],[1.2518029,43.5956282],[1.2518029,43.5949409],[1.2350437,43.5947847],[1.2350437,43.5945972],[1.2239572,43.5945972],[1.2239357,43.5994708],[1.2139708,43.599299],[1.2138845,43.6046408],[1.2020647,43.6044846],[1.2019464,43.61048],[1.1924294,43.6103695],[1.1919978,43.6328791]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2011","name":"Toulouse - Orthophotoplan 2011","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2011/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2013","name":"Toulouse - Orthophotoplan 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Toulouse-Orthophotoplan-2015","name":"Toulouse - Orthophotoplan 2015","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2015/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"id":"Tours-Orthophoto-2008_2010","name":"Tours - Orthophotos 2008-2010","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours/{zoom}/{x}/{y}","scaleExtent":[0,20],"polygon":[[[0.5457462,47.465264],[0.54585,47.4608163],[0.5392188,47.4606983],[0.5393484,47.456243],[0.5327959,47.4561003],[0.5329011,47.451565],[0.52619,47.4514013],[0.5265854,47.4424884],[0.5000941,47.4420739],[0.5002357,47.4375835],[0.4936014,47.4374324],[0.4937,47.4329285],[0.4606141,47.4324593],[0.4607248,47.4279827],[0.4541016,47.4278125],[0.454932,47.4053921],[0.4615431,47.4054476],[0.4619097,47.3964924],[0.4684346,47.3966005],[0.4691319,47.3786415],[0.4757125,47.3787609],[0.4762116,47.3652018],[0.4828297,47.3653499],[0.4829611,47.3608321],[0.4763543,47.360743],[0.476654,47.3517263],[0.4700497,47.3516186],[0.4701971,47.3471313],[0.4637503,47.3470104],[0.4571425,47.3424146],[0.4572922,47.3379061],[0.4506741,47.3378081],[0.4508379,47.3333051],[0.4442212,47.3332032],[0.4443809,47.328711],[0.4311392,47.3284977],[0.4316262,47.3150004],[0.4382432,47.3151136],[0.4383815,47.3106174],[0.4714487,47.3111374],[0.4713096,47.3156565],[0.477888,47.3157542],[0.4780733,47.3112802],[0.4846826,47.3113639],[0.4848576,47.3068686],[0.4914359,47.3069803],[0.491745,47.2979733],[0.4851578,47.2978722],[0.4854269,47.2888744],[0.4788485,47.2887697],[0.4791574,47.2797818],[0.4857769,47.2799005],[0.4859107,47.2753885],[0.492539,47.2755029],[0.4926669,47.2710127],[0.4992986,47.2711066],[0.4994296,47.2666116],[0.5192658,47.2669245],[0.5194225,47.2624231],[0.5260186,47.2625205],[0.5258735,47.2670183],[0.5456972,47.2673383],[0.5455537,47.2718283],[0.5587737,47.2720366],[0.5586259,47.2765185],[0.5652252,47.2766278],[0.5650848,47.2811206],[0.5716753,47.2812285],[0.5715223,47.2857217],[0.5781436,47.2858299],[0.5779914,47.2903294],[0.5846023,47.2904263],[0.5843076,47.2994231],[0.597499,47.2996094],[0.5976637,47.2951375],[0.6571596,47.2960036],[0.6572988,47.2915091],[0.6705019,47.2917186],[0.6703475,47.2962082],[0.6836175,47.2963688],[0.6834322,47.3008929],[0.690062,47.3009558],[0.6899241,47.3054703],[0.7362019,47.3061157],[0.7360848,47.3106063],[0.7559022,47.3108935],[0.7557718,47.315392],[0.7623755,47.3154716],[0.7622314,47.3199941],[0.7754911,47.3201546],[0.77497,47.3388218],[0.7745786,47.351628],[0.7680363,47.3515901],[0.767589,47.3605298],[0.7742443,47.3606238],[0.7733465,47.3921266],[0.7667434,47.3920195],[0.7664411,47.4010837],[0.7730647,47.4011115],[0.7728868,47.4101297],[0.7661849,47.4100226],[0.7660267,47.4145044],[0.7527613,47.4143038],[0.7529788,47.4098086],[0.7462373,47.4097016],[0.7459424,47.4232208],[0.7392324,47.4231451],[0.738869,47.4366116],[0.7323267,47.4365171],[0.7321869,47.4410556],[0.7255048,47.44098],[0.7254209,47.4453479],[0.7318793,47.4454803],[0.7318514,47.4501126],[0.7384496,47.450226],[0.7383098,47.454631],[0.7449359,47.4547444],[0.7443209,47.4771985],[0.7310685,47.4769717],[0.7309008,47.4815445],[0.7176205,47.4812611],[0.7177883,47.4768394],[0.69777,47.4764993],[0.6980496,47.4719827],[0.6914514,47.4718882],[0.6917309,47.4630241],[0.6851048,47.4629295],[0.684937,47.4673524],[0.678255,47.4673335],[0.6779754,47.4762158],[0.6714051,47.4761592],[0.6710417,47.4881952],[0.6577334,47.4879685],[0.6578173,47.48504],[0.6511911,47.4848322],[0.6514707,47.4758568],[0.6448166,47.4757245],[0.6449284,47.4712646],[0.6117976,47.4707543],[0.6118815,47.4663129],[0.6052833,47.4661239],[0.6054231,47.4616631],[0.5988808,47.4615497],[0.5990206,47.4570886],[0.572488,47.4566916],[0.5721805,47.4656513],[0.5457462,47.465264]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s) Plus 2008"},{"id":"Tours-Orthophoto-2013","name":"Tours - Orthophotos 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[0.427093505859375,47.26199018174824],[0.427093505859375,47.50096732311069],[0.814361572265625,47.50096732311069],[0.814361572265625,47.26199018174824],[0.427093505859375,47.26199018174824]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s)plus 2013"},{"id":"US_Forest_Service_roads","name":"U.S. Forest Service roads","type":"tms","template":"http://osm.cycle.travel/forest/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]]},{"id":"Zuerich-zh_uebersichtsplan-tms","name":"Übersichtsplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_uebersichtsplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[0,21],"polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"id":"USGS-Large_Scale","name":"USGS Large Scale Imagery","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.us/usgs_large_scale/{zoom}/{x}/{y}.jpg","scaleExtent":[12,20],"polygon":[[[-123.2549305,48.7529029],[-123.2549305,48.5592263],[-123.192224,48.5592263],[-123.192224,48.4348366],[-122.9419646,48.4348366],[-122.9419646,48.3720812],[-122.8806229,48.3720812],[-122.8806229,48.3094763],[-122.8167566,48.3094763],[-122.8167566,48.1904587],[-123.0041133,48.1904587],[-123.0041133,48.1275918],[-123.058416,48.1275918],[-123.058416,48.190514],[-123.254113,48.190514],[-123.254113,48.1274982],[-123.3706593,48.1274982],[-123.3706593,48.1908403],[-124.0582632,48.1908403],[-124.0582632,48.253442],[-124.1815163,48.253442],[-124.1815163,48.3164666],[-124.4319117,48.3164666],[-124.4319117,48.3782613],[-124.5564618,48.3782613],[-124.5564618,48.4408305],[-124.7555107,48.4408305],[-124.7555107,48.1914986],[-124.8185282,48.1914986],[-124.8185282,48.1228381],[-124.7552951,48.1228381],[-124.7552951,47.5535253],[-124.3812108,47.5535253],[-124.3812108,47.1218696],[-124.1928897,47.1218696],[-124.1928897,43.7569431],[-124.4443382,43.7569431],[-124.4443382,43.1425556],[-124.6398855,43.1425556],[-124.6398855,42.6194503],[-124.4438525,42.6194503],[-124.4438525,39.8080662],[-123.8815685,39.8080662],[-123.8815685,39.1102825],[-123.75805,39.1102825],[-123.75805,38.4968799],[-123.2702803,38.4968799],[-123.2702803,37.9331905],[-122.8148084,37.9331905],[-122.8148084,37.8019606],[-122.5664316,37.8019606],[-122.5664316,36.9319611],[-121.8784026,36.9319611],[-121.8784026,36.6897596],[-122.0034748,36.6897596],[-122.0034748,36.4341056],[-121.9414159,36.4341056],[-121.9414159,35.9297636],[-121.5040977,35.9297636],[-121.5040977,35.8100273],[-121.3790276,35.8100273],[-121.3790276,35.4239164],[-120.9426515,35.4239164],[-120.9426515,35.1849683],[-120.8171978,35.1849683],[-120.8171978,35.1219894],[-120.6918447,35.1219894],[-120.6918447,34.4966794],[-120.5045898,34.4966794],[-120.5045898,34.4339651],[-120.0078775,34.4339651],[-120.0078775,34.3682626],[-119.5283517,34.3682626],[-119.5283517,34.0576434],[-119.0060985,34.0576434],[-119.0060985,33.9975267],[-118.5046259,33.9975267],[-118.5046259,33.8694631],[-118.4413209,33.8694631],[-118.4413209,33.6865253],[-118.066912,33.6865253],[-118.066912,33.3063832],[-117.5030045,33.3063832],[-117.5030045,33.0500337],[-117.3188195,33.0500337],[-117.3188195,32.6205888],[-117.1917023,32.6205888],[-117.1917023,32.4974566],[-116.746496,32.4974566],[-116.746496,32.5609161],[-115.9970138,32.5609161],[-115.9970138,32.6264942],[-114.8808125,32.6264942],[-114.8808125,32.4340796],[-114.6294474,32.4340796],[-114.6294474,32.3731636],[-114.4447437,32.3731636],[-114.4447437,32.3075418],[-114.2557628,32.3075418],[-114.2557628,32.2444561],[-114.0680274,32.2444561],[-114.0680274,32.1829113],[-113.8166499,32.1829113],[-113.8166499,32.1207622],[-113.6307421,32.1207622],[-113.6307421,32.0565099],[-113.4417495,32.0565099],[-113.4417495,31.9984372],[-113.2546027,31.9984372],[-113.2546027,31.9325434],[-113.068072,31.9325434],[-113.068072,31.8718062],[-112.8161105,31.8718062],[-112.8161105,31.8104171],[-112.6308756,31.8104171],[-112.6308756,31.7464723],[-112.4418918,31.7464723],[-112.4418918,31.6856001],[-112.257192,31.6856001],[-112.257192,31.6210352],[-112.0033787,31.6210352],[-112.0033787,31.559584],[-111.815619,31.559584],[-111.815619,31.4970238],[-111.6278586,31.4970238],[-111.6278586,31.4339867],[-111.4418978,31.4339867],[-111.4418978,31.3733859],[-111.2559708,31.3733859],[-111.2559708,31.3113225],[-108.1845822,31.3113225],[-108.1845822,31.7459502],[-106.5065055,31.7459502],[-106.5065055,31.6842308],[-106.3797265,31.6842308],[-106.3797265,31.621752],[-106.317434,31.621752],[-106.317434,31.4968167],[-106.2551769,31.4968167],[-106.2551769,31.4344889],[-106.1924698,31.4344889],[-106.1924698,31.3721296],[-106.0039212,31.3721296],[-106.0039212,31.309328],[-105.9416582,31.309328],[-105.9416582,31.2457547],[-105.8798174,31.2457547],[-105.8798174,31.1836194],[-105.8162349,31.1836194],[-105.8162349,31.1207155],[-105.6921198,31.1207155],[-105.6921198,31.0584835],[-105.6302881,31.0584835],[-105.6302881,30.9328271],[-105.5044418,30.9328271],[-105.5044418,30.8715864],[-105.4412973,30.8715864],[-105.4412973,30.808463],[-105.3781497,30.808463],[-105.3781497,30.7471828],[-105.1904658,30.7471828],[-105.1904658,30.6843231],[-105.1286244,30.6843231],[-105.1286244,30.6199737],[-105.0036504,30.6199737],[-105.0036504,30.5589058],[-104.9417962,30.5589058],[-104.9417962,30.4963236],[-104.8782018,30.4963236],[-104.8782018,30.3098261],[-104.8155257,30.3098261],[-104.8155257,30.2478305],[-104.7536079,30.2478305],[-104.7536079,29.9353916],[-104.690949,29.9353916],[-104.690949,29.8090156],[-104.6291301,29.8090156],[-104.6291301,29.6843577],[-104.5659869,29.6843577],[-104.5659869,29.6223459],[-104.5037188,29.6223459],[-104.5037188,29.5595436],[-104.4410072,29.5595436],[-104.4410072,29.4974832],[-104.2537551,29.4974832],[-104.2537551,29.3716718],[-104.1291984,29.3716718],[-104.1291984,29.3091621],[-104.0688737,29.3091621],[-104.0688737,29.2467276],[-103.8187309,29.2467276],[-103.8187309,29.1843076],[-103.755736,29.1843076],[-103.755736,29.1223174],[-103.5667542,29.1223174],[-103.5667542,29.0598119],[-103.5049819,29.0598119],[-103.5049819,28.9967506],[-103.3165753,28.9967506],[-103.3165753,28.9346923],[-103.0597572,28.9346923],[-103.0597572,29.0592965],[-102.9979694,29.0592965],[-102.9979694,29.1212855],[-102.9331397,29.1212855],[-102.9331397,29.1848575],[-102.8095989,29.1848575],[-102.8095989,29.2526154],[-102.8701345,29.2526154],[-102.8701345,29.308096],[-102.8096681,29.308096],[-102.8096681,29.3715484],[-102.7475655,29.3715484],[-102.7475655,29.5581899],[-102.684554,29.5581899],[-102.684554,29.6847655],[-102.4967764,29.6847655],[-102.4967764,29.7457694],[-102.3086647,29.7457694],[-102.3086647,29.8086627],[-102.1909323,29.8086627],[-102.1909323,29.7460097],[-101.5049914,29.7460097],[-101.5049914,29.6846777],[-101.3805796,29.6846777],[-101.3805796,29.5594459],[-101.3175057,29.5594459],[-101.3175057,29.4958934],[-101.1910075,29.4958934],[-101.1910075,29.4326115],[-101.067501,29.4326115],[-101.067501,29.308808],[-100.9418897,29.308808],[-100.9418897,29.2456231],[-100.8167271,29.2456231],[-100.8167271,29.1190449],[-100.7522672,29.1190449],[-100.7522672,29.0578214],[-100.6925358,29.0578214],[-100.6925358,28.8720431],[-100.6290158,28.8720431],[-100.6290158,28.8095363],[-100.5679901,28.8095363],[-100.5679901,28.622554],[-100.5040411,28.622554],[-100.5040411,28.5583804],[-100.4421832,28.5583804],[-100.4421832,28.4968266],[-100.379434,28.4968266],[-100.379434,28.3092865],[-100.3171942,28.3092865],[-100.3171942,28.1835681],[-100.254483,28.1835681],[-100.254483,28.1213885],[-100.1282282,28.1213885],[-100.1282282,28.059215],[-100.0659537,28.059215],[-100.0659537,27.9966087],[-100.0023855,27.9966087],[-100.0023855,27.9332152],[-99.9426497,27.9332152],[-99.9426497,27.7454658],[-99.816851,27.7454658],[-99.816851,27.6834301],[-99.7541346,27.6834301],[-99.7541346,27.6221543],[-99.6291629,27.6221543],[-99.6291629,27.5588977],[-99.5672838,27.5588977],[-99.5672838,27.4353752],[-99.5041798,27.4353752],[-99.5041798,27.3774021],[-99.5671796,27.3774021],[-99.5671796,27.2463726],[-99.504975,27.2463726],[-99.504975,26.9965649],[-99.4427427,26.9965649],[-99.4427427,26.872803],[-99.3800633,26.872803],[-99.3800633,26.8068179],[-99.3190684,26.8068179],[-99.3190684,26.7473614],[-99.2537541,26.7473614],[-99.2537541,26.6210068],[-99.1910617,26.6210068],[-99.1910617,26.4956737],[-99.1300639,26.4956737],[-99.1300639,26.3713808],[-99.0029473,26.3713808],[-99.0029473,26.3093836],[-98.816572,26.3093836],[-98.816572,26.2457762],[-98.6920082,26.2457762],[-98.6920082,26.1837096],[-98.4440896,26.1837096],[-98.4440896,26.1217217],[-98.3823181,26.1217217],[-98.3823181,26.0596488],[-98.2532707,26.0596488],[-98.2532707,25.9986871],[-98.0109084,25.9986871],[-98.0109084,25.9932255],[-97.6932319,25.9932255],[-97.6932319,25.9334103],[-97.6313904,25.9334103],[-97.6313904,25.8695893],[-97.5046779,25.8695893],[-97.5046779,25.8073488],[-97.3083401,25.8073488],[-97.3083401,25.8731159],[-97.2456326,25.8731159],[-97.2456326,25.9353731],[-97.1138939,25.9353731],[-97.1138939,27.6809179],[-97.0571035,27.6809179],[-97.0571035,27.8108242],[-95.5810766,27.8108242],[-95.5810766,28.7468827],[-94.271041,28.7468827],[-94.271041,29.5594076],[-92.5029947,29.5594076],[-92.5029947,29.4974754],[-91.8776216,29.4974754],[-91.8776216,29.3727013],[-91.378418,29.3727013],[-91.378418,29.2468326],[-91.3153953,29.2468326],[-91.3153953,29.1844301],[-91.1294702,29.1844301],[-91.1294702,29.1232559],[-91.0052632,29.1232559],[-91.0052632,28.9968437],[-89.4500159,28.9968437],[-89.4500159,28.8677422],[-88.8104309,28.8677422],[-88.8104309,30.1841864],[-85.8791527,30.1841864],[-85.8791527,29.5455038],[-84.8368083,29.5455038],[-84.8368083,29.6225158],[-84.7482786,29.6225158],[-84.7482786,29.683624],[-84.685894,29.683624],[-84.685894,29.7468386],[-83.6296975,29.7468386],[-83.6296975,29.4324361],[-83.3174937,29.4324361],[-83.3174937,29.0579442],[-82.879659,29.0579442],[-82.879659,27.7453529],[-82.8182822,27.7453529],[-82.8182822,26.9290868],[-82.3796782,26.9290868],[-82.3796782,26.3694183],[-81.8777106,26.3694183],[-81.8777106,25.805971],[-81.5036862,25.805971],[-81.5036862,25.7474753],[-81.4405462,25.7474753],[-81.4405462,25.6851489],[-81.3155883,25.6851489],[-81.3155883,25.5600985],[-81.2538534,25.5600985],[-81.2538534,25.4342361],[-81.1902012,25.4342361],[-81.1902012,25.1234341],[-81.1288133,25.1234341],[-81.1288133,25.0619389],[-81.0649231,25.0619389],[-81.0649231,24.8157807],[-81.6289469,24.8157807],[-81.6289469,24.7538367],[-81.6907173,24.7538367],[-81.6907173,24.6899374],[-81.8173189,24.6899374],[-81.8173189,24.6279161],[-82.1910041,24.6279161],[-82.1910041,24.496294],[-81.6216596,24.496294],[-81.6216596,24.559484],[-81.372006,24.559484],[-81.372006,24.6220687],[-81.0593278,24.6220687],[-81.0593278,24.684826],[-80.9347147,24.684826],[-80.9347147,24.7474828],[-80.7471081,24.7474828],[-80.7471081,24.8100618],[-80.3629898,24.8100618],[-80.3629898,25.1175858],[-80.122344,25.1175858],[-80.122344,25.7472357],[-80.0588458,25.7472357],[-80.0588458,26.3708251],[-79.995837,26.3708251],[-79.995837,26.9398003],[-80.0587265,26.9398003],[-80.0587265,27.1277466],[-80.1226251,27.1277466],[-80.1226251,27.2534279],[-80.1846956,27.2534279],[-80.1846956,27.3781229],[-80.246175,27.3781229],[-80.246175,27.5658729],[-80.3094768,27.5658729],[-80.3094768,27.7530311],[-80.3721485,27.7530311],[-80.3721485,27.8774451],[-80.4351457,27.8774451],[-80.4351457,28.0033366],[-80.4966078,28.0033366],[-80.4966078,28.1277326],[-80.5587159,28.1277326],[-80.5587159,28.3723509],[-80.4966335,28.3723509],[-80.4966335,29.5160326],[-81.1213644,29.5160326],[-81.1213644,31.6846966],[-80.6018723,31.6846966],[-80.6018723,32.2475309],[-79.4921024,32.2475309],[-79.4921024,32.9970261],[-79.1116488,32.9970261],[-79.1116488,33.3729457],[-78.6153621,33.3729457],[-78.6153621,33.8097638],[-77.9316963,33.8097638],[-77.9316963,33.8718243],[-77.8692252,33.8718243],[-77.8692252,34.0552454],[-77.6826392,34.0552454],[-77.6826392,34.2974598],[-77.2453509,34.2974598],[-77.2453509,34.5598585],[-76.4973277,34.5598585],[-76.4973277,34.622796],[-76.4337602,34.622796],[-76.4337602,34.6849285],[-76.373212,34.6849285],[-76.373212,34.7467674],[-76.3059364,34.7467674],[-76.3059364,34.808551],[-76.2468017,34.808551],[-76.2468017,34.8728418],[-76.1825922,34.8728418],[-76.1825922,34.9335332],[-76.120814,34.9335332],[-76.120814,34.9952359],[-75.9979015,34.9952359],[-75.9979015,35.0578182],[-75.870338,35.0578182],[-75.870338,35.1219097],[-75.7462194,35.1219097],[-75.7462194,35.1818911],[-75.4929694,35.1818911],[-75.4929694,35.3082988],[-75.4325662,35.3082988],[-75.4325662,35.7542495],[-75.4969907,35.7542495],[-75.4969907,37.8105602],[-75.3082972,37.8105602],[-75.3082972,37.8720088],[-75.245601,37.8720088],[-75.245601,37.9954849],[-75.1828751,37.9954849],[-75.1828751,38.0585079],[-75.1184793,38.0585079],[-75.1184793,38.2469091],[-75.0592098,38.2469091],[-75.0592098,38.3704316],[-74.9948111,38.3704316],[-74.9948111,38.8718417],[-74.4878252,38.8718417],[-74.4878252,39.3089428],[-74.1766317,39.3089428],[-74.1766317,39.6224653],[-74.0567045,39.6224653],[-74.0567045,39.933178],[-73.9959035,39.933178],[-73.9959035,40.1854852],[-73.9341593,40.1854852],[-73.9341593,40.4959486],[-73.8723024,40.4959486],[-73.8723024,40.5527135],[-71.8074506,40.5527135],[-71.8074506,41.3088005],[-70.882512,41.3088005],[-70.882512,41.184978],[-70.7461947,41.184978],[-70.7461947,41.3091865],[-70.4337553,41.3091865],[-70.4337553,41.4963885],[-69.9334281,41.4963885],[-69.9334281,41.6230802],[-69.869857,41.6230802],[-69.869857,41.8776895],[-69.935791,41.8776895],[-69.935791,42.0032342],[-69.9975823,42.0032342],[-69.9975823,42.0650191],[-70.0606103,42.0650191],[-70.0606103,42.1294348],[-70.5572884,42.1294348],[-70.5572884,43.2487079],[-70.4974097,43.2487079],[-70.4974097,43.3092194],[-70.3704249,43.3092194],[-70.3704249,43.371963],[-70.3085701,43.371963],[-70.3085701,43.4969879],[-70.183921,43.4969879],[-70.183921,43.6223531],[-70.057583,43.6223531],[-70.057583,43.6850173],[-69.7455247,43.6850173],[-69.7455247,43.7476571],[-69.2472845,43.7476571],[-69.2472845,43.8107035],[-69.0560701,43.8107035],[-69.0560701,43.8717247],[-68.9950522,43.8717247],[-68.9950522,43.9982022],[-68.4963672,43.9982022],[-68.4963672,44.0597368],[-68.3081038,44.0597368],[-68.3081038,44.122137],[-68.1851802,44.122137],[-68.1851802,44.3081382],[-67.9956019,44.3081382],[-67.9956019,44.3727489],[-67.8103041,44.3727489],[-67.8103041,44.435178],[-67.4965289,44.435178],[-67.4965289,44.4968776],[-67.37102,44.4968776],[-67.37102,44.5600642],[-67.1848753,44.5600642],[-67.1848753,44.6213345],[-67.1221208,44.6213345],[-67.1221208,44.6867918],[-67.059365,44.6867918],[-67.059365,44.7473657],[-66.9311098,44.7473657],[-66.9311098,44.9406566],[-66.994683,44.9406566],[-66.994683,45.0024514],[-67.0595847,45.0024514],[-67.0595847,45.1273377],[-67.1201974,45.1273377],[-67.1201974,45.1910115],[-67.2469811,45.1910115],[-67.2469811,45.253442],[-67.3177546,45.253442],[-67.3177546,45.1898369],[-67.370749,45.1898369],[-67.370749,45.2534001],[-67.4326888,45.2534001],[-67.4326888,45.3083409],[-67.3708571,45.3083409],[-67.3708571,45.4396986],[-67.4305573,45.4396986],[-67.4305573,45.4950095],[-67.37099,45.4950095],[-67.37099,45.6264543],[-67.6214982,45.6264543],[-67.6214982,45.6896133],[-67.683828,45.6896133],[-67.683828,45.753259],[-67.7462097,45.753259],[-67.7462097,47.1268165],[-67.8700141,47.1268165],[-67.8700141,47.1900278],[-67.9323803,47.1900278],[-67.9323803,47.2539678],[-67.9959387,47.2539678],[-67.9959387,47.3149737],[-68.1206676,47.3149737],[-68.1206676,47.3780823],[-68.4423175,47.3780823],[-68.4423175,47.3166082],[-68.6314305,47.3166082],[-68.6314305,47.2544676],[-68.9978037,47.2544676],[-68.9978037,47.439895],[-69.0607223,47.439895],[-69.0607223,47.5047558],[-69.2538122,47.5047558],[-69.2538122,47.4398084],[-69.3179284,47.4398084],[-69.3179284,47.378601],[-69.4438546,47.378601],[-69.4438546,47.3156274],[-69.5038204,47.3156274],[-69.5038204,47.2525839],[-69.5667838,47.2525839],[-69.5667838,47.1910884],[-69.6303478,47.1910884],[-69.6303478,47.128701],[-69.6933103,47.128701],[-69.6933103,47.0654307],[-69.7557063,47.0654307],[-69.7557063,47.0042751],[-69.8180391,47.0042751],[-69.8180391,46.9415344],[-69.8804023,46.9415344],[-69.8804023,46.8792519],[-69.9421674,46.8792519],[-69.9421674,46.8177399],[-70.0063088,46.8177399],[-70.0063088,46.6920295],[-70.0704265,46.6920295],[-70.0704265,46.4425926],[-70.1945902,46.4425926],[-70.1945902,46.3785887],[-70.2562047,46.3785887],[-70.2562047,46.3152628],[-70.3203651,46.3152628],[-70.3203651,46.0651209],[-70.3814988,46.0651209],[-70.3814988,45.93552],[-70.3201618,45.93552],[-70.3201618,45.879479],[-70.4493131,45.879479],[-70.4493131,45.7538713],[-70.5070021,45.7538713],[-70.5070021,45.6916912],[-70.6316642,45.6916912],[-70.6316642,45.6291619],[-70.7575538,45.6291619],[-70.7575538,45.4414685],[-70.8809878,45.4414685],[-70.8809878,45.3780612],[-71.13328,45.3780612],[-71.13328,45.3151452],[-71.3830282,45.3151452],[-71.3830282,45.253416],[-71.5076448,45.253416],[-71.5076448,45.0655726],[-73.9418929,45.0655726],[-73.9418929,45.0031242],[-74.7469725,45.0031242],[-74.7469725,45.0649003],[-74.8800964,45.0649003],[-74.8800964,45.0029023],[-75.0662455,45.0029023],[-75.0662455,44.9415167],[-75.2539363,44.9415167],[-75.2539363,44.8776043],[-75.3789648,44.8776043],[-75.3789648,44.8153462],[-75.4431283,44.8153462],[-75.4431283,44.7536053],[-75.5666566,44.7536053],[-75.5666566,44.6909879],[-75.6290205,44.6909879],[-75.6290205,44.6284958],[-75.7540484,44.6284958],[-75.7540484,44.566385],[-75.817312,44.566385],[-75.817312,44.5028932],[-75.8799549,44.5028932],[-75.8799549,44.3784946],[-76.1300319,44.3784946],[-76.1300319,44.3159227],[-76.1926961,44.3159227],[-76.1926961,44.2534378],[-76.3182619,44.2534378],[-76.3182619,44.1916726],[-76.3792975,44.1916726],[-76.3792975,44.0653733],[-76.4427584,44.0653733],[-76.4427584,43.9963825],[-76.317027,43.9963825],[-76.317027,43.9414581],[-76.5076611,43.9414581],[-76.5076611,43.8723335],[-76.3829974,43.8723335],[-76.3829974,43.8091872],[-76.2534102,43.8091872],[-76.2534102,43.5665222],[-76.5064833,43.5665222],[-76.5064833,43.5033881],[-76.6331208,43.5033881],[-76.6331208,43.4432252],[-76.6951085,43.4432252],[-76.6951085,43.3786858],[-76.8177798,43.3786858],[-76.8177798,43.318066],[-77.682,43.318066],[-77.682,43.3789376],[-78.0565883,43.3789376],[-78.0565883,43.4396918],[-78.4389748,43.4396918],[-78.4389748,43.3794382],[-78.8803396,43.3794382],[-78.8803396,43.3149724],[-79.1298858,43.3149724],[-79.1298858,43.2429286],[-79.0669615,43.2429286],[-79.0669615,43.1299931],[-79.1298858,43.1299931],[-79.1298858,43.0577305],[-79.071264,43.0577305],[-79.071264,42.9294906],[-78.943264,42.9294906],[-78.943264,42.7542165],[-79.069439,42.7542165],[-79.069439,42.6941622],[-79.133439,42.6941622],[-79.133439,42.6296973],[-79.1947499,42.6296973],[-79.1947499,42.5663538],[-79.3786827,42.5663538],[-79.3786827,42.5033425],[-79.4442961,42.5033425],[-79.4442961,42.4410614],[-79.5679936,42.4410614],[-79.5679936,42.3775264],[-79.6906154,42.3775264],[-79.6906154,42.3171086],[-79.8164642,42.3171086],[-79.8164642,42.2534481],[-80.0052373,42.2534481],[-80.0052373,42.1909188],[-80.1916829,42.1909188],[-80.1916829,42.1272555],[-80.3167992,42.1272555],[-80.3167992,42.0669857],[-80.5063234,42.0669857],[-80.5063234,42.0034331],[-80.6930471,42.0034331],[-80.6930471,41.9415141],[-80.9440403,41.9415141],[-80.9440403,41.8781193],[-81.1942729,41.8781193],[-81.1942729,41.8166455],[-81.3190089,41.8166455],[-81.3190089,41.7545453],[-81.4418435,41.7545453],[-81.4418435,41.690965],[-81.5053523,41.690965],[-81.5053523,41.6301643],[-82.7470081,41.6301643],[-82.7470081,41.7536942],[-82.8839135,41.7536942],[-82.8839135,41.5656075],[-82.9957195,41.5656075],[-82.9957195,41.6270375],[-83.1257796,41.6270375],[-83.1257796,41.6878411],[-83.2474733,41.6878411],[-83.2474733,41.7536942],[-83.3737305,41.7536942],[-83.3737305,41.809276],[-83.3106019,41.809276],[-83.3106019,41.8716064],[-83.2474733,41.8716064],[-83.2474733,41.9361393],[-83.1843447,41.9361393],[-83.1843447,41.9960851],[-83.1207681,41.9960851],[-83.1207681,42.2464812],[-83.0589194,42.2464812],[-83.0589194,42.3089555],[-82.8685328,42.3089555],[-82.8685328,42.3717652],[-82.8072219,42.3717652],[-82.8072219,42.558553],[-82.7553745,42.558553],[-82.7553745,42.4954945],[-82.5599041,42.4954945],[-82.5599041,42.558553],[-82.4967755,42.558553],[-82.4967755,42.6833607],[-82.4328863,42.6833607],[-82.4328863,42.9342196],[-82.3700552,42.9342196],[-82.3700552,43.0648071],[-82.4328863,43.0648071],[-82.4328863,43.1917566],[-82.4947464,43.1917566],[-82.4947464,43.5034627],[-82.557133,43.5034627],[-82.557133,43.8160901],[-82.6197884,43.8160901],[-82.6197884,43.9422098],[-82.6839499,43.9422098],[-82.6839499,44.0022641],[-82.7465346,44.0022641],[-82.7465346,44.0670545],[-82.8708696,44.0670545],[-82.8708696,44.1291935],[-83.008517,44.1291935],[-83.008517,44.0664786],[-83.1336086,44.0664786],[-83.1336086,44.0053949],[-83.2414522,44.0053949],[-83.2414522,44.9962034],[-83.1806112,44.9962034],[-83.1806112,45.067302],[-83.2455172,45.067302],[-83.2455172,45.1287382],[-83.3065878,45.1287382],[-83.3065878,45.2551509],[-83.3706087,45.2551509],[-83.3706087,45.3165923],[-83.4325644,45.3165923],[-83.4325644,45.3792105],[-83.6178415,45.3792105],[-83.6178415,45.4419665],[-83.8084291,45.4419665],[-83.8084291,45.5036189],[-84.0550718,45.5036189],[-84.0550718,45.5647907],[-84.1235181,45.5647907],[-84.1235181,45.6287845],[-84.1807534,45.6287845],[-84.1807534,45.6914688],[-84.3111554,45.6914688],[-84.3111554,45.9337076],[-83.8209974,45.9337076],[-83.8209974,45.8725113],[-83.4968086,45.8725113],[-83.4968086,45.9337076],[-83.4338066,45.9337076],[-83.4338066,46.0016863],[-83.4962697,46.0016863],[-83.4962697,46.0668178],[-83.5599956,46.0668178],[-83.5599956,46.1261576],[-83.9954558,46.1261576],[-83.9954558,46.1931747],[-84.0591816,46.1931747],[-84.0591816,46.3814972],[-84.1152614,46.3814972],[-84.1152614,46.4953584],[-84.0591816,46.4953584],[-84.0591816,46.5682653],[-84.2579545,46.5682653],[-84.2579545,46.5051232],[-84.3071879,46.5051232],[-84.3071879,46.5682653],[-84.4415364,46.5682653],[-84.4415364,46.504525],[-84.9965729,46.504525],[-84.9965729,46.6842882],[-84.9298158,46.6842882],[-84.9298158,46.818077],[-85.3165894,46.818077],[-85.3165894,46.7535825],[-87.5562645,46.7535825],[-87.5562645,47.4407371],[-87.6825361,47.4407371],[-87.6825361,47.5035554],[-88.2560738,47.5035554],[-88.2560738,47.4433716],[-88.4417419,47.4433716],[-88.4417419,47.3789949],[-88.50683,47.3789949],[-88.50683,47.3153881],[-88.6312821,47.3153881],[-88.6312821,47.2539782],[-88.7569636,47.2539782],[-88.7569636,47.1934682],[-88.8838253,47.1934682],[-88.8838253,47.1284735],[-88.9434208,47.1284735],[-88.9434208,47.0662127],[-89.0708726,47.0662127],[-89.0708726,47.0026826],[-89.2565553,47.0026826],[-89.2565553,46.9410806],[-90.3677669,46.9410806],[-90.3677669,47.6844827],[-90.3069978,47.6844827],[-90.3069978,47.7460174],[-89.994859,47.7460174],[-89.994859,47.8082719],[-89.8048615,47.8082719],[-89.8048615,47.8700562],[-89.6797699,47.8700562],[-89.6797699,47.9339637],[-89.4933757,47.9339637],[-89.4933757,47.9957956],[-89.4284697,47.9957956],[-89.4284697,48.0656377],[-89.9932739,48.0656377],[-89.9932739,48.1282966],[-90.7455933,48.1282966],[-90.7455933,48.1893056],[-90.8087291,48.1893056],[-90.8087291,48.2522065],[-91.067763,48.2522065],[-91.067763,48.1916658],[-91.1946247,48.1916658],[-91.1946247,48.1279027],[-91.6814196,48.1279027],[-91.6814196,48.2525994],[-91.9321927,48.2525994],[-91.9321927,48.3142454],[-91.9929683,48.3142454],[-91.9929683,48.3780845],[-92.3189383,48.3780845],[-92.3189383,48.2529081],[-92.3732233,48.2529081],[-92.3732233,48.3153385],[-92.4322288,48.3153385],[-92.4322288,48.4411448],[-92.4977248,48.4411448],[-92.4977248,48.501781],[-92.5679413,48.501781],[-92.5679413,48.439579],[-92.6210462,48.439579],[-92.6210462,48.5650783],[-92.8086835,48.5650783],[-92.8086835,48.6286865],[-92.8086835,48.6267365],[-92.933185,48.6267365],[-92.933185,48.6922145],[-93.0051716,48.6922145],[-93.0051716,48.6282965],[-93.1225924,48.6282965],[-93.1225924,48.6922145],[-93.3190806,48.6922145],[-93.3190806,48.6267365],[-93.5049477,48.6267365],[-93.5049477,48.5635164],[-93.7474601,48.5635164],[-93.7474601,48.6267365],[-93.8135461,48.6267365],[-93.8135461,48.6898775],[-94.2453121,48.6898775],[-94.2453121,48.7554327],[-94.6183171,48.7554327],[-94.6183171,48.941036],[-94.6809018,48.941036],[-94.6809018,49.0029737],[-94.7441532,49.0029737],[-94.7441532,49.2536079],[-94.8084069,49.2536079],[-94.8084069,49.3784134],[-95.1192391,49.3784134],[-95.1192391,49.4425264],[-95.1934341,49.4425264],[-95.1934341,49.0035292],[-96.87069,49.0035292],[-96.87069,49.0656063],[-99.0049312,49.0656063],[-99.0049312,49.0050714],[-109.3699257,49.0050714],[-109.3699257,49.0668231],[-109.5058746,49.0668231],[-109.5058746,49.0050714],[-114.1830014,49.0050714],[-114.1830014,49.0687317],[-114.7578709,49.0687317],[-114.7578709,49.0050714],[-115.433731,49.0050714],[-115.433731,49.0671412],[-116.5062706,49.0671412],[-116.5062706,49.0050714],[-117.3089504,49.0050714],[-117.3089504,49.0659803],[-119.882945,49.0659803],[-119.882945,49.0050714],[-120.1208555,49.0050714],[-120.1208555,49.0678367],[-121.4451636,49.0678367],[-121.4451636,49.0050714],[-121.9311808,49.0050714],[-121.9311808,49.0656099],[-122.817484,49.0656099],[-122.817484,49.0029143],[-122.8795155,49.0029143],[-122.8795155,48.9347018],[-122.8174629,48.9347018],[-122.8174629,48.8101998],[-122.7538859,48.8101998],[-122.7538859,48.7533758],[-122.8712937,48.7533758],[-122.8712937,48.8153948],[-123.0055391,48.8153948],[-123.0055391,48.7529529],[-123.1296926,48.7529529],[-123.1296926,48.6902201],[-123.1838197,48.6902201],[-123.1838197,48.7529029],[-123.2549305,48.7529029]],[[-122.9341743,37.7521547],[-122.9347457,37.6842013],[-123.0679013,37.6849023],[-123.0673747,37.7475251],[-123.1292603,37.7478506],[-123.1286894,37.815685],[-123.0590687,37.8153192],[-123.0595947,37.7528143],[-122.9341743,37.7521547]],[[-71.6299464,41.2540893],[-71.4966465,41.2541393],[-71.4965596,41.122965],[-71.6298594,41.1229149],[-71.6299464,41.2540893]],[[-70.3184265,41.3775196],[-70.3183384,41.2448243],[-70.1906612,41.2448722],[-70.1906239,41.1886019],[-69.9336025,41.1886984],[-69.933729,41.3791941],[-69.9950664,41.3791712],[-69.995109,41.443159],[-70.0707828,41.4431307],[-70.0706972,41.3144915],[-70.2461667,41.3144258],[-70.2462087,41.3775467],[-70.3184265,41.3775196]],[[-68.9403374,43.9404062],[-68.6856948,43.9404977],[-68.6856475,43.8721797],[-68.7465405,43.8721577],[-68.7464976,43.8102529],[-68.8090782,43.8102304],[-68.8090343,43.746728],[-68.8773094,43.7467034],[-68.8773544,43.8117826],[-68.9402483,43.8117599],[-68.9403374,43.9404062]],[[-123.1291466,49.0645144],[-122.9954224,49.0645144],[-122.9954224,48.9343243],[-123.1291466,48.9343243],[-123.1291466,49.0645144]],[[-82.9407144,24.7535913],[-82.8719398,24.7535913],[-82.8719398,24.6905653],[-82.7446233,24.6905653],[-82.7446233,24.6214593],[-82.8088038,24.6214593],[-82.8088038,24.5594908],[-82.9407144,24.5594908],[-82.9407144,24.7535913]]]},{"id":"USGS-Scanned_Topographic","name":"USGS Topographic Maps","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.us/usgs_scanned_topos/{zoom}/{x}/{y}.png","polygon":[[[-125.990173,48.9962416],[-125.989419,47.9948396],[-123.9929739,47.9955062],[-123.9922429,47.0059202],[-125.988688,47.0052409],[-125.9879604,46.0015618],[-123.9939396,46.0022529],[-123.9925238,43.9961708],[-124.9931832,43.9958116],[-124.9918175,41.9942149],[-125.9851789,41.9938465],[-125.9838655,40.0076111],[-123.9833285,40.0083757],[-123.9814115,37.002615],[-122.21903,37.0033173],[-122.2184144,36.011671],[-122.020087,36.011751],[-122.0188591,33.9961766],[-119.9787757,33.9970206],[-119.9775867,31.9987658],[-114.0122833,32.00129],[-114.0116894,30.9862401],[-105.998294,30.9896679],[-105.9971419,28.9901065],[-102.0210506,28.9918418],[-102.0204916,28.00733],[-100.0062436,28.0082173],[-100.0051143,25.991909],[-98.0109067,25.9928035],[-98.0103613,25.0063461],[-97.0161086,25.0067957],[-97.016654,25.9932494],[-95.9824825,25.9937132],[-95.9835999,27.9891175],[-94.0200898,27.9899826],[-94.0206586,28.9918129],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-86.0271719,28.9953016],[-84.0187909,28.9961781],[-84.017095,25.9817708],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-80.0245309,32.0161282],[-78.0066484,32.0169819],[-78.0072238,32.9894278],[-77.8807233,32.9894807],[-77.8813253,33.9955918],[-76.0115411,33.9963653],[-76.0121459,34.9952552],[-74.0068449,34.9960749],[-74.0099997,40.0084254],[-72.0013745,40.0091931],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8804173,42.00893],[-69.9927682,42.0088883],[-69.9934462,43.0105166],[-67.9845366,43.0112496],[-67.985224,44.0103812],[-65.9892568,44.0110975],[-65.9921237,47.9993584],[-70.006442,47.9980181],[-70.005708,47.0042007],[-72.023686,47.003514],[-72.0222508,45.0059846],[-78.0146667,45.0038705],[-78.0139662,44.0026998],[-80.029686,44.0019763],[-80.0290052,43.0122994],[-81.995479,43.011582],[-81.9982986,47.0042713],[-87.505706,47.0023972],[-87.5064535,48.0142702],[-88.0260889,48.0140968],[-88.026838,49.0086686],[-93.9981078,49.0067142],[-93.9988778,50.0086456],[-96.0138899,50.0079995],[-96.0131199,49.0060547],[-125.990173,48.9962416]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-159.0030121,21.499196],[-159.0027422,20.9951068],[-157.5083185,20.995803],[-157.5080519,20.4960241],[-155.966889,20.4967444],[-155.9674267,21.5028287],[-157.5044717,21.5021151],[-157.5047384,21.9984962],[-159.0090946,21.9978002],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-168.006102,68.9941463],[-168.0047628,68.0107853],[-165.4842481,68.0112562],[-165.4829337,67.0037303],[-168.0034485,67.0032389],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-168.0009882,64.9989798],[-167.9998282,63.9982374],[-164.9871288,63.9988964],[-164.9860062,62.9950845],[-167.9987057,62.9944019],[-167.9946035,59.0153692],[-162.5027857,59.0167799],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-160.5045719,55.9968161],[-164.012195,55.9958373],[-164.0113186,55.00107],[-165.994782,55.0005023],[-165.9941266,54.2400584],[-168.0002944,54.2394734],[-168.0000986,54.0094921],[-170.0156134,54.0089011],[-170.0147683,53.0016446],[-171.9993636,53.0010487],[-171.9989488,52.4977745],[-176.0083239,52.4965566],[-176.0081186,52.2452555],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-176.0073212,51.2560472],[-176.0075146,51.4980163],[-171.9981395,51.4992617],[-171.9985419,51.9985373],[-167.9984317,51.9997661],[-167.9994645,53.2560877],[-165.9932968,53.2566866],[-165.9939308,54.0100804],[-159.0067205,54.0121291],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-158.0199473,55.9975094],[-151.9963213,55.9991902],[-151.9981536,57.9986536],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-136.6872422,57.9991267],[-136.6863158,57.0016688],[-135.9973698,57.001856],[-135.9964667,56.0030544],[-134.6717732,56.003424],[-134.6708865,54.9969623],[-133.9956734,54.9971556],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-131.9787378,59.9933094],[-138.0071813,59.991805],[-138.0082158,61.0125755],[-140.9874011,61.0118551],[-140.99984,71.0039309],[-154.5023956,71.0017377],[-154.5039632,71.9983391],[-157.499048,71.9978773],[-157.4974758,70.9982877],[-163.0233611,70.9973899],[-163.0218273,69.9707435],[-164.9730896,69.97041],[-164.9717003,68.994689],[-168.006102,68.9941463]],[[-168.5133204,62.8689586],[-168.5144423,63.8765677],[-172.0202755,63.8757975],[-172.0191536,62.8681608],[-168.5133204,62.8689586]],[[-170.9947111,59.9954089],[-170.995726,60.9969787],[-174.0045311,60.9962508],[-174.0035162,59.9946581],[-170.9947111,59.9954089]],[[-156.0717261,20.2854602],[-154.7940471,20.2860582],[-154.7933145,18.9029464],[-156.0709936,18.9023432],[-156.0717261,20.2854602]],[[-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"},"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/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/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(file) {
42806         if (lodash.isUndefined(file)) {
42807             return '';
42808         }
42809
42810         var lastDotIndex = file.name.lastIndexOf('.');
42811         if (lastDotIndex < 0) {
42812             return '';
42813         }
42814
42815         return file.name.substr(lastDotIndex);
42816     }
42817
42818
42819     function parseSaveAndZoom(extension, data) {
42820         if (extension === '.gpx') {
42821             drawGpx.geojson(togeojson.gpx(toDom(data))).fitZoom();
42822         }
42823         else if (extension === '.kml') {
42824             drawGpx.geojson(togeojson.kml(toDom(data))).fitZoom();
42825         }
42826         else if (extension === '.geojson' || extension === '.json') {
42827             drawGpx.geojson(JSON.parse(data)).fitZoom();
42828         }
42829     }
42830
42831
42832     drawGpx.showLabels = function(_) {
42833         if (!arguments.length) return showLabels;
42834         showLabels = _;
42835         return this;
42836     };
42837
42838
42839     drawGpx.enabled = function(_) {
42840         if (!arguments.length) return svgGpx.enabled;
42841         svgGpx.enabled = _;
42842         dispatch$$1.call('change');
42843         return this;
42844     };
42845
42846
42847     drawGpx.hasGpx = function() {
42848         var geojson = svgGpx.geojson;
42849         return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42850     };
42851
42852
42853     drawGpx.geojson = function(gj) {
42854         if (!arguments.length) return svgGpx.geojson;
42855         if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42856         svgGpx.geojson = gj;
42857         dispatch$$1.call('change');
42858         return this;
42859     };
42860
42861
42862     drawGpx.url = function(url) {
42863         text(url, function(err, data) {
42864             if (!err) {
42865                 var extension = getExtension(url);
42866                 parseSaveAndZoom(extension, data);
42867             }
42868         });
42869         return this;
42870     };
42871
42872
42873     drawGpx.files = function(fileList) {
42874         if (!fileList.length) return this;
42875         var f = fileList[0],
42876             reader = new FileReader();
42877
42878         reader.onload = (function(file) {
42879             var extension = getExtension(file);
42880
42881             return function (e) {
42882                 parseSaveAndZoom(extension, e.target.result);
42883             };
42884         })(f);
42885
42886         reader.readAsText(f);
42887         return this;
42888     };
42889
42890
42891     drawGpx.fitZoom = function() {
42892         if (!this.hasGpx()) return this;
42893         var geojson = svgGpx.geojson;
42894
42895         var map$$1 = context.map(),
42896             viewport = map$$1.trimmedExtent().polygon(),
42897             coords = lodash.reduce(geojson.features, function(coords, feature) {
42898                 var c = feature.geometry.coordinates;
42899                 return lodash.union(coords, feature.geometry.type === 'Point' ? [c] : c);
42900             }, []);
42901
42902         if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42903             var extent$$1 = geoExtent$$1(bounds(geojson));
42904             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
42905         }
42906
42907         return this;
42908     };
42909
42910
42911     init();
42912     return drawGpx;
42913 }
42914
42915 function svgIcon(name, svgklass, useklass) {
42916     return function drawIcon(selection) {
42917         selection.selectAll('svg')
42918             .data([0])
42919             .enter()
42920             .append('svg')
42921             .attr('class', 'icon ' + (svgklass || ''))
42922             .append('use')
42923             .attr('xlink:href', name)
42924             .attr('class', useklass);
42925     };
42926 }
42927
42928 function svgLabels(projection, context) {
42929     var path$$1 = index$4(projection),
42930         detected = utilDetect(),
42931         baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
42932         rdrawn = index$9(),
42933         rskipped = index$9(),
42934         textWidthCache = {},
42935         entitybboxes = {};
42936
42937     // Listed from highest to lowest priority
42938     var labelStack = [
42939         ['line', 'aeroway', '*', 12],
42940         ['line', 'highway', 'motorway', 12],
42941         ['line', 'highway', 'trunk', 12],
42942         ['line', 'highway', 'primary', 12],
42943         ['line', 'highway', 'secondary', 12],
42944         ['line', 'highway', 'tertiary', 12],
42945         ['line', 'highway', '*', 12],
42946         ['line', 'railway', '*', 12],
42947         ['line', 'waterway', '*', 12],
42948         ['area', 'aeroway', '*', 12],
42949         ['area', 'amenity', '*', 12],
42950         ['area', 'building', '*', 12],
42951         ['area', 'historic', '*', 12],
42952         ['area', 'leisure', '*', 12],
42953         ['area', 'man_made', '*', 12],
42954         ['area', 'natural', '*', 12],
42955         ['area', 'shop', '*', 12],
42956         ['area', 'tourism', '*', 12],
42957         ['area', 'camp_site', '*', 12],
42958         ['point', 'aeroway', '*', 10],
42959         ['point', 'amenity', '*', 10],
42960         ['point', 'building', '*', 10],
42961         ['point', 'historic', '*', 10],
42962         ['point', 'leisure', '*', 10],
42963         ['point', 'man_made', '*', 10],
42964         ['point', 'natural', '*', 10],
42965         ['point', 'shop', '*', 10],
42966         ['point', 'tourism', '*', 10],
42967         ['point', 'camp_site', '*', 10],
42968         ['line', 'name', '*', 12],
42969         ['area', 'name', '*', 12],
42970         ['point', 'name', '*', 10]
42971     ];
42972
42973
42974     function blacklisted(preset) {
42975         var noIcons = ['building', 'landuse', 'natural'];
42976         return lodash.some(noIcons, function(s) {
42977             return preset.id.indexOf(s) >= 0;
42978         });
42979     }
42980
42981
42982     function get(array, prop) {
42983         return function(d, i) { return array[i][prop]; };
42984     }
42985
42986
42987     function textWidth(text$$1, size, elem) {
42988         var c = textWidthCache[size];
42989         if (!c) c = textWidthCache[size] = {};
42990
42991         if (c[text$$1]) {
42992             return c[text$$1];
42993
42994         } else if (elem) {
42995             c[text$$1] = elem.getComputedTextLength();
42996             return c[text$$1];
42997
42998         } else {
42999             var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
43000             if (str === null) {
43001                 return size / 3 * 2 * text$$1.length;
43002             } else {
43003                 return size / 3 * (2 * text$$1.length + str.length);
43004             }
43005         }
43006     }
43007
43008
43009     function drawLinePaths(selection$$1, entities, filter, classes, labels) {
43010         var paths = selection$$1.selectAll('path')
43011             .filter(filter)
43012             .data(entities, osmEntity$$1.key);
43013
43014         paths.exit()
43015             .remove();
43016
43017         paths.enter()
43018             .append('path')
43019             .style('stroke-width', get(labels, 'font-size'))
43020             .attr('id', function(d) { return 'labelpath-' + d.id; })
43021             .attr('class', classes)
43022             .merge(paths)
43023             .attr('d', get(labels, 'lineString'));
43024     }
43025
43026
43027     function drawLineLabels(selection$$1, entities, filter, classes, labels) {
43028         var texts = selection$$1.selectAll('text.' + classes)
43029             .filter(filter)
43030             .data(entities, osmEntity$$1.key);
43031
43032         texts.exit()
43033             .remove();
43034
43035         texts.enter()
43036             .append('text')
43037             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
43038             .attr('dy', baselineHack ? '0.35em' : null)
43039             .append('textPath')
43040             .attr('class', 'textpath');
43041
43042         texts = selection$$1.selectAll('text.' + classes);
43043
43044         texts.selectAll('.textpath')
43045             .filter(filter)
43046             .data(entities, osmEntity$$1.key)
43047             .attr('startOffset', '50%')
43048             .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
43049             .text(utilDisplayNameForPath);
43050     }
43051
43052
43053     function drawPointLabels(selection$$1, entities, filter, classes, labels) {
43054         var texts = selection$$1.selectAll('text.' + classes)
43055             .filter(filter)
43056             .data(entities, osmEntity$$1.key);
43057
43058         texts.exit()
43059             .remove();
43060
43061         texts = texts.enter()
43062             .append('text')
43063             .attr('class', function(d, i) {
43064                 return classes + ' ' + labels[i].classes + ' ' + d.id;
43065             })
43066             .merge(texts);
43067
43068         texts
43069             .attr('x', get(labels, 'x'))
43070             .attr('y', get(labels, 'y'))
43071             .style('text-anchor', get(labels, 'textAnchor'))
43072             .text(utilDisplayName)
43073             .each(function(d, i) {
43074                 textWidth(utilDisplayName(d), labels[i].height, this);
43075             });
43076     }
43077
43078
43079     function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
43080         entities = entities.filter(hasText);
43081         labels = labels.filter(hasText);
43082         drawPointLabels(selection$$1, entities, filter, classes, labels);
43083
43084         function hasText(d, i) {
43085             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
43086         }
43087     }
43088
43089
43090     function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
43091         var icons = selection$$1.selectAll('use.' + classes)
43092             .filter(filter)
43093             .data(entities, osmEntity$$1.key);
43094
43095         icons.exit()
43096             .remove();
43097
43098         icons = icons.enter()
43099             .append('use')
43100             .attr('class', 'icon ' + classes)
43101             .attr('width', '17px')
43102             .attr('height', '17px')
43103             .merge(icons);
43104
43105         icons
43106             .attr('transform', get(labels, 'transform'))
43107             .attr('xlink:href', function(d) {
43108                 var icon = context.presets().match(d, context.graph()).icon;
43109                 return '#' + icon + '-15';
43110             });
43111     }
43112
43113
43114     function drawCollisionBoxes(selection$$1, rtree, which) {
43115         var showDebug = context.getDebug('collision'),
43116             classes = 'debug ' + which + ' ' +
43117                 (which === 'debug-skipped' ? 'orange' : 'yellow');
43118
43119         var debug = selection$$1.selectAll('.layer-label-debug')
43120                 .data(showDebug ? [true] : []);
43121
43122         debug.exit()
43123             .remove();
43124
43125         debug = debug.enter()
43126             .append('g')
43127             .attr('class', 'layer-label-debug')
43128             .merge(debug);
43129
43130         if (showDebug) {
43131             var gj = rtree.all().map(function(d) {
43132                 return { type: 'Polygon', coordinates: [[
43133                     [d.minX, d.minY],
43134                     [d.maxX, d.minY],
43135                     [d.maxX, d.maxY],
43136                     [d.minX, d.maxY],
43137                     [d.minX, d.minY]
43138                 ]]};
43139             });
43140
43141             var debugboxes = debug.selectAll('.' + which)
43142                 .data(gj);
43143
43144             debugboxes.exit()
43145                 .remove();
43146
43147             debugboxes = debugboxes.enter()
43148                 .append('path')
43149                 .attr('class', classes)
43150                 .merge(debugboxes);
43151
43152             debugboxes
43153                 .attr('d', index$4());
43154         }
43155     }
43156
43157
43158     function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
43159         var lowZoom = context.surface().classed('low-zoom');
43160
43161         var labelable = [], i, j, k, entity, geometry;
43162         for (i = 0; i < labelStack.length; i++) {
43163             labelable.push([]);
43164         }
43165
43166         if (fullRedraw) {
43167             rdrawn.clear();
43168             rskipped.clear();
43169             entitybboxes = {};
43170         } else {
43171             for (i = 0; i < entities.length; i++) {
43172                 entity = entities[i];
43173                 var toRemove = []
43174                     .concat(entitybboxes[entity.id] || [])
43175                     .concat(entitybboxes[entity.id + 'I'] || []);
43176
43177                 for (j = 0; j < toRemove.length; j++) {
43178                     rdrawn.remove(toRemove[j]);
43179                     rskipped.remove(toRemove[j]);
43180                 }
43181             }
43182         }
43183
43184         // Split entities into groups specified by labelStack
43185         for (i = 0; i < entities.length; i++) {
43186             entity = entities[i];
43187             geometry = entity.geometry(graph);
43188             if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43189
43190             var preset = geometry === 'area' && context.presets().match(entity, graph),
43191                 icon = preset && !blacklisted(preset) && preset.icon;
43192
43193             if (!icon && !utilDisplayName(entity))
43194                 continue;
43195
43196             for (k = 0; k < labelStack.length; k++) {
43197                 var matchGeom = labelStack[k][0],
43198                     matchKey = labelStack[k][1],
43199                     matchVal = labelStack[k][2],
43200                     hasVal = entity.tags[matchKey];
43201
43202                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
43203                     labelable[k].push(entity);
43204                     break;
43205                 }
43206             }
43207         }
43208
43209         var positions = {
43210             point: [],
43211             line: [],
43212             area: []
43213         };
43214
43215         var labelled = {
43216             point: [],
43217             line: [],
43218             area: []
43219         };
43220
43221         // Try and find a valid label for labellable entities
43222         for (k = 0; k < labelable.length; k++) {
43223             var fontSize = labelStack[k][3];
43224             for (i = 0; i < labelable[k].length; i++) {
43225                 entity = labelable[k][i];
43226                 geometry = entity.geometry(graph);
43227
43228                 var getName = (geometry === 'line') ? utilDisplayNameForPath : utilDisplayName,
43229                     name = getName(entity),
43230                     width = name && textWidth(name, fontSize),
43231                     p;
43232
43233                 if (geometry === 'point') {
43234                     p = getPointLabel(entity, width, fontSize, geometry);
43235                 } else if (geometry === 'vertex' && !lowZoom) {
43236                     // don't label vertices at low zoom because they don't have icons
43237                     p = getPointLabel(entity, width, fontSize, geometry);
43238                 } else if (geometry === 'line') {
43239                     p = getLineLabel(entity, width, fontSize);
43240                 } else if (geometry === 'area') {
43241                     p = getAreaLabel(entity, width, fontSize);
43242                 }
43243
43244                 if (p) {
43245                     if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
43246                     p.classes = geometry + ' tag-' + labelStack[k][1];
43247                     positions[geometry].push(p);
43248                     labelled[geometry].push(entity);
43249                 }
43250             }
43251         }
43252
43253
43254         function getPointLabel(entity, width, height, geometry) {
43255             var y = (geometry === 'point' ? -12 : 0),
43256                 pointOffsets = {
43257                     ltr: [15, y, 'start'],
43258                     rtl: [-15, y, 'end']
43259                 };
43260
43261             var coord = projection(entity.loc),
43262                 margin = 2,
43263                 offset = pointOffsets[textDirection],
43264                 p = {
43265                     height: height,
43266                     width: width,
43267                     x: coord[0] + offset[0],
43268                     y: coord[1] + offset[1],
43269                     textAnchor: offset[2]
43270                 },
43271                 bbox;
43272
43273             if (textDirection === 'rtl') {
43274                 bbox = {
43275                     minX: p.x - width - margin,
43276                     minY: p.y - (height / 2) - margin,
43277                     maxX: p.x + margin,
43278                     maxY: p.y + (height / 2) + margin
43279                 };
43280             } else {
43281                 bbox = {
43282                     minX: p.x - margin,
43283                     minY: p.y - (height / 2) - margin,
43284                     maxX: p.x + width + margin,
43285                     maxY: p.y + (height / 2) + margin
43286                 };
43287             }
43288
43289             if (tryInsert([bbox], entity.id, true)) {
43290                 return p;
43291             }
43292         }
43293
43294
43295         function getLineLabel(entity, width, height) {
43296             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
43297                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
43298                 length = geoPathLength(nodes);
43299
43300             if (length < width + 20) return;
43301
43302             // % along the line to attempt to place the label
43303             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
43304                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
43305             var margin = 3;
43306
43307             for (var i = 0; i < lineOffsets.length; i++) {
43308                 var offset = lineOffsets[i],
43309                     middle = offset / 100 * length,
43310                     start = middle - width / 2;
43311
43312                 if (start < 0 || start + width > length) continue;
43313
43314                 // generate subpath and ignore paths that are invalid or don't cross viewport.
43315                 var sub = subpath(nodes, start, start + width);
43316                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
43317                     continue;
43318                 }
43319
43320                 var isReverse = reverse(sub);
43321                 if (isReverse) {
43322                     sub = sub.reverse();
43323                 }
43324
43325                 var bboxes = [],
43326                     boxsize = (height + 2) / 2;
43327
43328                 for (var j = 0; j < sub.length - 1; j++) {
43329                     var a = sub[j];
43330                     var b = sub[j + 1];
43331                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
43332
43333                     for (var box = 0; box < num; box++) {
43334                         var p = geoInterp(a, b, box / num);
43335                         var x0 = p[0] - boxsize - margin;
43336                         var y0 = p[1] - boxsize - margin;
43337                         var x1 = p[0] + boxsize + margin;
43338                         var y1 = p[1] + boxsize + margin;
43339
43340                         bboxes.push({
43341                             minX: Math.min(x0, x1),
43342                             minY: Math.min(y0, y1),
43343                             maxX: Math.max(x0, x1),
43344                             maxY: Math.max(y0, y1)
43345                         });
43346                     }
43347                 }
43348
43349                 if (tryInsert(bboxes, entity.id, false)) {
43350                     return {
43351                         'font-size': height + 2,
43352                         lineString: lineString(sub),
43353                         startOffset: offset + '%'
43354                     };
43355                 }
43356             }
43357
43358             function reverse(p) {
43359                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
43360                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
43361             }
43362
43363             function lineString(nodes) {
43364                 return 'M' + nodes.join('L');
43365             }
43366
43367             function subpath(nodes, from, to) {
43368                 var sofar = 0,
43369                     start, end, i0, i1;
43370
43371                 for (var i = 0; i < nodes.length - 1; i++) {
43372                     var a = nodes[i],
43373                         b = nodes[i + 1];
43374                     var current = geoEuclideanDistance(a, b);
43375                     var portion;
43376                     if (!start && sofar + current >= from) {
43377                         portion = (from - sofar) / current;
43378                         start = [
43379                             a[0] + portion * (b[0] - a[0]),
43380                             a[1] + portion * (b[1] - a[1])
43381                         ];
43382                         i0 = i + 1;
43383                     }
43384                     if (!end && sofar + current >= to) {
43385                         portion = (to - sofar) / current;
43386                         end = [
43387                             a[0] + portion * (b[0] - a[0]),
43388                             a[1] + portion * (b[1] - a[1])
43389                         ];
43390                         i1 = i + 1;
43391                     }
43392                     sofar += current;
43393                 }
43394
43395                 var ret = nodes.slice(i0, i1);
43396                 ret.unshift(start);
43397                 ret.push(end);
43398                 return ret;
43399             }
43400         }
43401
43402
43403         function getAreaLabel(entity, width, height) {
43404             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
43405                 extent$$1 = entity.extent(graph),
43406                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
43407
43408             if (isNaN(centroid[0]) || entitywidth < 20) return;
43409
43410             var iconSize = 20,
43411                 iconX = centroid[0] - (iconSize / 2),
43412                 iconY = centroid[1] - (iconSize / 2),
43413                 margin = 2,
43414                 textOffset = iconSize + margin,
43415                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
43416
43417             var bbox = {
43418                 minX: iconX,
43419                 minY: iconY,
43420                 maxX: iconX + iconSize,
43421                 maxY: iconY + iconSize
43422             };
43423
43424             // try to add icon
43425             if (tryInsert([bbox], entity.id + 'I', true)) {
43426                 if (width && entitywidth >= width + 20) {
43427                     var labelX = centroid[0],
43428                         labelY = centroid[1] + textOffset;
43429
43430                     bbox = {
43431                         minX: labelX - (width / 2) - margin,
43432                         minY: labelY - (height / 2) - margin,
43433                         maxX: labelX + (width / 2) + margin,
43434                         maxY: labelY + (height / 2) + margin
43435                     };
43436
43437                     // try to add label
43438                     if (tryInsert([bbox], entity.id, true)) {
43439                         p.x = labelX;
43440                         p.y = labelY;
43441                         p.textAnchor = 'middle';
43442                         p.height = height;
43443                     }
43444                 }
43445
43446                 return p;
43447             }
43448         }
43449
43450
43451         function tryInsert(bboxes, id, saveSkipped) {
43452             var skipped = false,
43453                 bbox;
43454
43455             for (var i = 0; i < bboxes.length; i++) {
43456                 bbox = bboxes[i];
43457                 bbox.id = id;
43458
43459                 // Check that label is visible
43460                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
43461                     skipped = true;
43462                     break;
43463                 }
43464                 if (rdrawn.collides(bbox)) {
43465                     skipped = true;
43466                     break;
43467                 }
43468             }
43469
43470             entitybboxes[id] = bboxes;
43471
43472             if (skipped) {
43473                 if (saveSkipped) {
43474                     rskipped.load(bboxes);
43475                 }
43476             } else {
43477                 rdrawn.load(bboxes);
43478             }
43479
43480             return !skipped;
43481         }
43482
43483
43484         var label = selection$$1.selectAll('.layer-label'),
43485             halo = selection$$1.selectAll('.layer-halo');
43486
43487         // points
43488         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
43489         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
43490
43491         // lines
43492         drawLinePaths(halo, labelled.line, filter, '', positions.line);
43493         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
43494         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
43495
43496         // areas
43497         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
43498         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
43499         drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
43500         drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area);
43501
43502         // debug
43503         drawCollisionBoxes(label, rskipped, 'debug-skipped');
43504         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
43505
43506         selection$$1.call(filterLabels);
43507     }
43508
43509
43510     function filterLabels(selection$$1) {
43511         var layers = selection$$1
43512             .selectAll('.layer-label, .layer-halo');
43513
43514         layers.selectAll('.proximate')
43515             .classed('proximate', false);
43516
43517         var mouse$$1 = context.mouse(),
43518             graph = context.graph(),
43519             selectedIDs = context.selectedIDs(),
43520             ids = [],
43521             pad, bbox;
43522
43523         // hide labels near the mouse
43524         if (mouse$$1) {
43525             pad = 20;
43526             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43527             ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43528         }
43529
43530         // hide labels along selected ways, or near selected vertices
43531         for (var i = 0; i < selectedIDs.length; i++) {
43532             var entity = graph.hasEntity(selectedIDs[i]);
43533             if (!entity) continue;
43534             var geometry = entity.geometry(graph);
43535
43536             if (geometry === 'line') {
43537                 ids.push(selectedIDs[i]);
43538             } else if (geometry === 'vertex') {
43539                 var point = context.projection(entity.loc);
43540                 pad = 10;
43541                 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43542                 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43543             }
43544         }
43545
43546         layers.selectAll(utilEntitySelector(ids))
43547             .classed('proximate', true);
43548     }
43549
43550
43551     var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43552
43553
43554     drawLabels.observe = function(selection$$1) {
43555         var listener = function() { throttleFilterLabels(selection$$1); };
43556         selection$$1.on('mousemove.hidelabels', listener);
43557         context.on('enter.hidelabels', listener);
43558     };
43559
43560
43561     drawLabels.off = function(selection$$1) {
43562         throttleFilterLabels.cancel();
43563         selection$$1.on('mousemove.hidelabels', null);
43564         context.on('enter.hidelabels', null);
43565     };
43566
43567
43568     return drawLabels;
43569 }
43570
43571 // Copies a variable number of methods from source to target.
43572 function utilRebind(target, source) {
43573     var i = 1, n = arguments.length, method;
43574     while (++i < n) {
43575         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
43576     }
43577     return target;
43578 }
43579
43580 // Method is assumed to be a standard D3 getter-setter:
43581 // If passed with no arguments, gets the value.
43582 // If passed with arguments, sets the value and returns the target.
43583 function d3_rebind(target, source, method) {
43584     return function() {
43585         var value = method.apply(source, arguments);
43586         return value === source ? target : value;
43587     };
43588 }
43589
43590 function refresh(selection, node) {
43591     var cr = node.getBoundingClientRect();
43592     var prop = [cr.width, cr.height];
43593     selection.property('__dimensions__', prop);
43594     return prop;
43595 }
43596
43597 function utilGetDimensions(selection, force) {
43598     if (!selection || selection.empty()) {
43599         return [0, 0];
43600     }
43601     var node = selection.node(),
43602         cached = selection.property('__dimensions__');
43603     return (!cached || force) ? refresh(selection, node) : cached;
43604 }
43605
43606
43607 function utilSetDimensions(selection, dimensions) {
43608     if (!selection || selection.empty()) {
43609         return selection;
43610     }
43611     var node = selection.node();
43612     if (dimensions === null) {
43613         refresh(selection, node);
43614         return selection;
43615     }
43616     return selection
43617         .property('__dimensions__', [dimensions[0], dimensions[1]])
43618         .attr('width', dimensions[0])
43619         .attr('height', dimensions[1]);
43620 }
43621
43622 function svgPointTransform(projection) {
43623     return function(entity) {
43624         // http://jsperf.com/short-array-join
43625         var pt = projection(entity.loc);
43626         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43627     };
43628 }
43629
43630 function d3geoTile() {
43631   var size = [960, 500],
43632       scale = 256,
43633       scaleExtent = [0, 20],
43634       translate = [size[0] / 2, size[1] / 2],
43635       zoomDelta = 0;
43636
43637   function bound(_) {
43638       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43639   }
43640
43641   function tile() {
43642     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43643         z0 = bound(Math.round(z + zoomDelta)),
43644         k = Math.pow(2, z - z0 + 8),
43645         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43646         tiles = [],
43647         cols = sequence(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43648         rows = sequence(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43649
43650     rows.forEach(function(y) {
43651       cols.forEach(function(x) {
43652         tiles.push([x, y, z0]);
43653       });
43654     });
43655
43656     tiles.translate = origin;
43657     tiles.scale = k;
43658
43659     return tiles;
43660   }
43661
43662   tile.scaleExtent = function(_) {
43663     if (!arguments.length) return scaleExtent;
43664     scaleExtent = _;
43665     return tile;
43666   };
43667
43668   tile.size = function(_) {
43669     if (!arguments.length) return size;
43670     size = _;
43671     return tile;
43672   };
43673
43674   tile.scale = function(_) {
43675     if (!arguments.length) return scale;
43676     scale = _;
43677     return tile;
43678   };
43679
43680   tile.translate = function(_) {
43681     if (!arguments.length) return translate;
43682     translate = _;
43683     return tile;
43684   };
43685
43686   tile.zoomDelta = function(_) {
43687     if (!arguments.length) return zoomDelta;
43688     zoomDelta = +_;
43689     return tile;
43690   };
43691
43692   return tile;
43693 }
43694
43695 /* global Mapillary:false */
43696 var apibase = 'https://a.mapillary.com/v2/';
43697 var viewercss = 'mapillary-js/mapillary.min.css';
43698 var viewerjs = 'mapillary-js/mapillary.min.js';
43699 var trafficocss = 'traffico/stylesheets/traffico.css';
43700 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43701 var maxResults = 1000;
43702 var tileZoom = 14;
43703 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43704 var mapillaryCache;
43705 var mapillaryClicks;
43706 var mapillaryImage;
43707 var mapillarySignDefs;
43708 var mapillaryViewer;
43709
43710
43711 function abortRequest(i) {
43712     i.abort();
43713 }
43714
43715
43716 function nearNullIsland(x, y, z) {
43717     if (z >= 7) {
43718         var center = Math.pow(2, z - 1),
43719             width = Math.pow(2, z - 6),
43720             min$$1 = center - (width / 2),
43721             max$$1 = center + (width / 2) - 1;
43722         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43723     }
43724     return false;
43725 }
43726
43727
43728 function maxPageAtZoom(z) {
43729     if (z < 15)   return 2;
43730     if (z === 15) return 5;
43731     if (z === 16) return 10;
43732     if (z === 17) return 20;
43733     if (z === 18) return 40;
43734     if (z > 18)   return 80;
43735 }
43736
43737
43738 function getTiles(projection) {
43739     var s = projection.scale() * 2 * Math.PI,
43740         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43741         ts = 256 * Math.pow(2, z - tileZoom),
43742         origin = [
43743             s / 2 - projection.translate()[0],
43744             s / 2 - projection.translate()[1]];
43745
43746     return d3geoTile()
43747         .scaleExtent([tileZoom, tileZoom])
43748         .scale(s)
43749         .size(projection.clipExtent()[1])
43750         .translate(projection.translate())()
43751         .map(function(tile) {
43752             var x = tile[0] * ts - origin[0],
43753                 y = tile[1] * ts - origin[1];
43754
43755             return {
43756                 id: tile.toString(),
43757                 xyz: tile,
43758                 extent: geoExtent$$1(
43759                     projection.invert([x, y + ts]),
43760                     projection.invert([x + ts, y])
43761                 )
43762             };
43763         });
43764 }
43765
43766
43767 function loadTiles(which, url, projection) {
43768     var s = projection.scale() * 2 * Math.PI,
43769         currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43770
43771     var tiles = getTiles(projection).filter(function(t) {
43772             return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43773         });
43774
43775     lodash.filter(which.inflight, function(v, k) {
43776         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43777         if (!wanted) delete which.inflight[k];
43778         return !wanted;
43779     }).map(abortRequest);
43780
43781     tiles.forEach(function(tile) {
43782         loadNextTilePage(which, currZoom, url, tile);
43783     });
43784 }
43785
43786
43787 function loadNextTilePage(which, currZoom, url, tile) {
43788     var cache = mapillaryCache[which],
43789         rect = tile.extent.rectangle(),
43790         maxPages = maxPageAtZoom(currZoom),
43791         nextPage = cache.nextPage[tile.id] || 0;
43792
43793     if (nextPage > maxPages) return;
43794
43795     var id = tile.id + ',' + String(nextPage);
43796     if (cache.loaded[id] || cache.inflight[id]) return;
43797
43798     cache.inflight[id] = json(url +
43799         utilQsString({
43800             geojson: 'true',
43801             limit: maxResults,
43802             page: nextPage,
43803             client_id: clientId,
43804             min_lon: rect[0],
43805             min_lat: rect[1],
43806             max_lon: rect[2],
43807             max_lat: rect[3]
43808         }), function(err, data) {
43809             cache.loaded[id] = true;
43810             delete cache.inflight[id];
43811             if (err || !data.features || !data.features.length) return;
43812
43813             var features = [],
43814                 feature, loc, d;
43815
43816             for (var i = 0; i < data.features.length; i++) {
43817                 feature = data.features[i];
43818                 loc = feature.geometry.coordinates;
43819                 d = { key: feature.properties.key, loc: loc };
43820                 if (which === 'images') d.ca = feature.properties.ca;
43821                 if (which === 'signs') d.signs = feature.properties.rects;
43822
43823                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43824             }
43825
43826             cache.rtree.load(features);
43827
43828             if (which === 'images') dispatch$2.call('loadedImages');
43829             if (which === 'signs') dispatch$2.call('loadedSigns');
43830
43831             if (data.features.length === maxResults) {  // more pages to load
43832                 cache.nextPage[tile.id] = nextPage + 1;
43833                 loadNextTilePage(which, currZoom, url, tile);
43834             } else {
43835                 cache.nextPage[tile.id] = Infinity;     // no more pages to load
43836             }
43837         }
43838     );
43839 }
43840
43841
43842 // partition viewport into `psize` x `psize` regions
43843 function partitionViewport(psize, projection) {
43844     var dimensions = projection.clipExtent()[1];
43845     psize = psize || 16;
43846     var cols = sequence(0, dimensions[0], psize),
43847         rows = sequence(0, dimensions[1], psize),
43848         partitions = [];
43849
43850     rows.forEach(function(y) {
43851         cols.forEach(function(x) {
43852             var min$$1 = [x, y + psize],
43853                 max$$1 = [x + psize, y];
43854             partitions.push(
43855                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43856         });
43857     });
43858
43859     return partitions;
43860 }
43861
43862
43863 // no more than `limit` results per partition.
43864 function searchLimited(psize, limit, projection, rtree) {
43865     limit = limit || 3;
43866
43867     var partitions = partitionViewport(psize, projection);
43868     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43869         return rtree.search(extent$$1.bbox())
43870             .slice(0, limit)
43871             .map(function(d) { return d.data; });
43872     })));
43873 }
43874
43875
43876
43877 var serviceMapillary = {
43878
43879     init: function() {
43880         if (!mapillaryCache) {
43881             this.reset();
43882         }
43883
43884         this.event = utilRebind(this, dispatch$2, 'on');
43885     },
43886
43887     reset: function() {
43888         var cache = mapillaryCache;
43889
43890         if (cache) {
43891             if (cache.images && cache.images.inflight) {
43892                 lodash.forEach(cache.images.inflight, abortRequest);
43893             }
43894             if (cache.signs && cache.signs.inflight) {
43895                 lodash.forEach(cache.signs.inflight, abortRequest);
43896             }
43897         }
43898
43899         mapillaryCache = {
43900             images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() },
43901             signs:  { inflight: {}, loaded: {}, nextPage: {}, rtree: index$9() }
43902         };
43903
43904         mapillaryImage = null;
43905         mapillaryClicks = [];
43906     },
43907
43908
43909     images: function(projection) {
43910         var psize = 16, limit = 3;
43911         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43912     },
43913
43914
43915     signs: function(projection) {
43916         var psize = 32, limit = 3;
43917         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43918     },
43919
43920
43921     signsSupported: function() {
43922         var detected = utilDetect();
43923         if (detected.ie) return false;
43924         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43925         return true;
43926     },
43927
43928
43929     signHTML: function(d) {
43930         if (!mapillarySignDefs) return;
43931
43932         var detectionPackage = d.signs[0].package,
43933             type = d.signs[0].type,
43934             country = detectionPackage.split('_')[1];
43935
43936         return mapillarySignDefs[country][type];
43937     },
43938
43939
43940     loadImages: function(projection) {
43941         var url = apibase + 'search/im/geojson?';
43942         loadTiles('images', url, projection);
43943     },
43944
43945
43946     loadSigns: function(context, projection) {
43947         var url = apibase + 'search/im/geojson/or?';
43948         loadTiles('signs', url, projection);
43949
43950         // load traffico css
43951         select('head').selectAll('#traffico')
43952             .data([0])
43953             .enter()
43954             .append('link')
43955             .attr('id', 'traffico')
43956             .attr('rel', 'stylesheet')
43957             .attr('href', context.asset(trafficocss));
43958
43959         // load traffico sign defs
43960         if (!mapillarySignDefs) {
43961             mapillarySignDefs = {};
43962             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
43963                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
43964                     if (err) return;
43965                     if (region === 'de') region = 'eu';
43966                     mapillarySignDefs[region] = data;
43967                 });
43968             });
43969         }
43970     },
43971
43972
43973     loadViewer: function(context) {
43974         var that = this;
43975         var wrap = select('#content').selectAll('.mapillary-wrap')
43976             .data([0]);
43977
43978         var enter = wrap.enter()
43979             .append('div')
43980             .attr('class', 'mapillary-wrap')
43981             .classed('al', true)       // 'al'=left,  'ar'=right
43982             .classed('hidden', true);
43983
43984         enter
43985             .append('button')
43986             .attr('class', 'thumb-hide')
43987             .on('click', function () { that.hideViewer(); })
43988             .append('div')
43989             .call(svgIcon('#icon-close'));
43990
43991         enter
43992             .append('div')
43993             .attr('id', 'mly')
43994             .attr('class', 'mly-wrapper')
43995             .classed('active', false);
43996
43997         // load mapillary-viewercss
43998         select('head').selectAll('#mapillary-viewercss')
43999             .data([0])
44000             .enter()
44001             .append('link')
44002             .attr('id', 'mapillary-viewercss')
44003             .attr('rel', 'stylesheet')
44004             .attr('href', context.asset(viewercss));
44005
44006         // load mapillary-viewerjs
44007         select('head').selectAll('#mapillary-viewerjs')
44008             .data([0])
44009             .enter()
44010             .append('script')
44011             .attr('id', 'mapillary-viewerjs')
44012             .attr('src', context.asset(viewerjs));
44013     },
44014
44015
44016     showViewer: function() {
44017         select('#content')
44018             .selectAll('.mapillary-wrap')
44019             .classed('hidden', false)
44020             .selectAll('.mly-wrapper')
44021             .classed('active', true);
44022
44023         return this;
44024     },
44025
44026
44027     hideViewer: function() {
44028         select('#content')
44029             .selectAll('.mapillary-wrap')
44030             .classed('hidden', true)
44031             .selectAll('.mly-wrapper')
44032             .classed('active', false);
44033
44034         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44035             .classed('selected', false);
44036
44037         mapillaryImage = null;
44038         return this;
44039     },
44040
44041
44042     updateViewer: function(imageKey, context) {
44043         if (!imageKey) return;
44044
44045         if (!mapillaryViewer) {
44046             this.initViewer(imageKey, context);
44047         } else {
44048             mapillaryViewer.moveToKey(imageKey);
44049         }
44050
44051         return this;
44052     },
44053
44054
44055     initViewer: function(imageKey, context) {
44056         var that = this;
44057         if (Mapillary && imageKey) {
44058             var opts = {
44059                 baseImageSize: 320,
44060                 component: {
44061                     cover: false,
44062                     keyboard: false
44063                 }
44064             };
44065
44066             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
44067             mapillaryViewer.on('nodechanged', nodeChanged);
44068         }
44069
44070         function nodeChanged(node) {
44071             var clicks = mapillaryClicks;
44072             var index = clicks.indexOf(node.key);
44073             if (index > -1) {    // nodechange initiated from clicking on a marker..
44074                 clicks.splice(index, 1);
44075             } else {             // nodechange initiated from the Mapillary viewer controls..
44076                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
44077                 context.map().centerEase(loc);
44078                 that.selectedImage(node.key, false);
44079             }
44080         }
44081     },
44082
44083
44084     selectedImage: function(imageKey, fromClick) {
44085         if (!arguments.length) return mapillaryImage;
44086
44087         mapillaryImage = imageKey;
44088         if (fromClick) {
44089             mapillaryClicks.push(imageKey);
44090         }
44091
44092         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
44093             .classed('selected', function(d) { return d.key === imageKey; });
44094
44095         return this;
44096     },
44097
44098
44099     cache: function(_) {
44100         if (!arguments.length) return mapillaryCache;
44101         mapillaryCache = _;
44102         return this;
44103     },
44104
44105
44106     signDefs: function(_) {
44107         if (!arguments.length) return mapillarySignDefs;
44108         mapillarySignDefs = _;
44109         return this;
44110     }
44111
44112 };
44113
44114 var apibase$1 = 'https://nominatim.openstreetmap.org/';
44115 var nominatimCache;
44116
44117
44118 var serviceNominatim = {
44119
44120     init: function() { nominatimCache = index$9(); },
44121     reset: function() { nominatimCache = index$9(); },
44122
44123
44124     countryCode: function (location, callback) {
44125         var countryCodes = nominatimCache.search(
44126             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
44127         );
44128
44129         if (countryCodes.length > 0) {
44130             return callback(null, countryCodes[0].data);
44131         }
44132
44133         json(apibase$1 + 'reverse?' +
44134             utilQsString({
44135                 format: 'json',
44136                 addressdetails: 1,
44137                 lat: location[1],
44138                 lon: location[0]
44139             }), function(err, result) {
44140                 if (err)
44141                     return callback(err);
44142                 else if (result && result.error)
44143                     return callback(result.error);
44144
44145                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
44146                 nominatimCache.insert(lodash.assign(extent$$1.bbox(),
44147                     { data: result.address.country_code }
44148                 ));
44149
44150                 callback(null, result.address.country_code);
44151             }
44152         );
44153     },
44154
44155
44156     search: function (val, callback) {
44157         var searchVal = encodeURIComponent(val);
44158         json(apibase$1 + 'search/' + searchVal + '?limit=10&format=json', callback);
44159     }
44160
44161 };
44162
44163 var hashes$1 = createCommonjsModule(function (module, exports) {
44164 /**
44165  * jshashes - https://github.com/h2non/jshashes
44166  * Released under the "New BSD" license
44167  *
44168  * Algorithms specification:
44169  *
44170  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
44171  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
44172  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44173  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44174  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
44175  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
44176  */
44177 (function() {
44178   var Hashes;
44179
44180   function utf8Encode(str) {
44181     var x, y, output = '',
44182       i = -1,
44183       l;
44184
44185     if (str && str.length) {
44186       l = str.length;
44187       while ((i += 1) < l) {
44188         /* Decode utf-16 surrogate pairs */
44189         x = str.charCodeAt(i);
44190         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
44191         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
44192           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44193           i += 1;
44194         }
44195         /* Encode output as utf-8 */
44196         if (x <= 0x7F) {
44197           output += String.fromCharCode(x);
44198         } else if (x <= 0x7FF) {
44199           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
44200             0x80 | (x & 0x3F));
44201         } else if (x <= 0xFFFF) {
44202           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44203             0x80 | ((x >>> 6) & 0x3F),
44204             0x80 | (x & 0x3F));
44205         } else if (x <= 0x1FFFFF) {
44206           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44207             0x80 | ((x >>> 12) & 0x3F),
44208             0x80 | ((x >>> 6) & 0x3F),
44209             0x80 | (x & 0x3F));
44210         }
44211       }
44212     }
44213     return output;
44214   }
44215
44216   function utf8Decode(str) {
44217     var i, ac, c1, c2, c3, arr = [],
44218       l;
44219     i = ac = c1 = c2 = c3 = 0;
44220
44221     if (str && str.length) {
44222       l = str.length;
44223       str += '';
44224
44225       while (i < l) {
44226         c1 = str.charCodeAt(i);
44227         ac += 1;
44228         if (c1 < 128) {
44229           arr[ac] = String.fromCharCode(c1);
44230           i += 1;
44231         } else if (c1 > 191 && c1 < 224) {
44232           c2 = str.charCodeAt(i + 1);
44233           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
44234           i += 2;
44235         } else {
44236           c2 = str.charCodeAt(i + 1);
44237           c3 = str.charCodeAt(i + 2);
44238           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
44239           i += 3;
44240         }
44241       }
44242     }
44243     return arr.join('');
44244   }
44245
44246   /**
44247    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44248    * to work around bugs in some JS interpreters.
44249    */
44250
44251   function safe_add(x, y) {
44252     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
44253       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44254     return (msw << 16) | (lsw & 0xFFFF);
44255   }
44256
44257   /**
44258    * Bitwise rotate a 32-bit number to the left.
44259    */
44260
44261   function bit_rol(num, cnt) {
44262     return (num << cnt) | (num >>> (32 - cnt));
44263   }
44264
44265   /**
44266    * Convert a raw string to a hex string
44267    */
44268
44269   function rstr2hex(input, hexcase) {
44270     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
44271       output = '',
44272       x, i = 0,
44273       l = input.length;
44274     for (; i < l; i += 1) {
44275       x = input.charCodeAt(i);
44276       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
44277     }
44278     return output;
44279   }
44280
44281   /**
44282    * Encode a string as utf-16
44283    */
44284
44285   function binb2rstr(input) {
44286     var i, l = input.length * 32,
44287       output = '';
44288     for (i = 0; i < l; i += 8) {
44289       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
44290     }
44291     return output;
44292   }
44293
44294   /**
44295    * Convert an array of little-endian words to a string
44296    */
44297
44298   function binl2rstr(input) {
44299     var i, l = input.length * 32,
44300       output = '';
44301     for (i = 0; i < l; i += 8) {
44302       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
44303     }
44304     return output;
44305   }
44306
44307   /**
44308    * Convert a raw string to an array of little-endian words
44309    * Characters >255 have their high-byte silently ignored.
44310    */
44311
44312   function rstr2binl(input) {
44313     var i, l = input.length * 8,
44314       output = Array(input.length >> 2),
44315       lo = output.length;
44316     for (i = 0; i < lo; i += 1) {
44317       output[i] = 0;
44318     }
44319     for (i = 0; i < l; i += 8) {
44320       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
44321     }
44322     return output;
44323   }
44324
44325   /**
44326    * Convert a raw string to an array of big-endian words
44327    * Characters >255 have their high-byte silently ignored.
44328    */
44329
44330   function rstr2binb(input) {
44331     var i, l = input.length * 8,
44332       output = Array(input.length >> 2),
44333       lo = output.length;
44334     for (i = 0; i < lo; i += 1) {
44335       output[i] = 0;
44336     }
44337     for (i = 0; i < l; i += 8) {
44338       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
44339     }
44340     return output;
44341   }
44342
44343   /**
44344    * Convert a raw string to an arbitrary string encoding
44345    */
44346
44347   function rstr2any(input, encoding) {
44348     var divisor = encoding.length,
44349       remainders = Array(),
44350       i, q, x, ld, quotient, dividend, output, full_length;
44351
44352     /* Convert to an array of 16-bit big-endian values, forming the dividend */
44353     dividend = Array(Math.ceil(input.length / 2));
44354     ld = dividend.length;
44355     for (i = 0; i < ld; i += 1) {
44356       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44357     }
44358
44359     /**
44360      * Repeatedly perform a long division. The binary array forms the dividend,
44361      * the length of the encoding is the divisor. Once computed, the quotient
44362      * forms the dividend for the next step. We stop when the dividend is zerHashes.
44363      * All remainders are stored for later use.
44364      */
44365     while (dividend.length > 0) {
44366       quotient = Array();
44367       x = 0;
44368       for (i = 0; i < dividend.length; i += 1) {
44369         x = (x << 16) + dividend[i];
44370         q = Math.floor(x / divisor);
44371         x -= q * divisor;
44372         if (quotient.length > 0 || q > 0) {
44373           quotient[quotient.length] = q;
44374         }
44375       }
44376       remainders[remainders.length] = x;
44377       dividend = quotient;
44378     }
44379
44380     /* Convert the remainders to the output string */
44381     output = '';
44382     for (i = remainders.length - 1; i >= 0; i--) {
44383       output += encoding.charAt(remainders[i]);
44384     }
44385
44386     /* Append leading zero equivalents */
44387     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
44388     for (i = output.length; i < full_length; i += 1) {
44389       output = encoding[0] + output;
44390     }
44391     return output;
44392   }
44393
44394   /**
44395    * Convert a raw string to a base-64 string
44396    */
44397
44398   function rstr2b64(input, b64pad) {
44399     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44400       output = '',
44401       len = input.length,
44402       i, j, triplet;
44403     b64pad = b64pad || '=';
44404     for (i = 0; i < len; i += 3) {
44405       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44406       for (j = 0; j < 4; j += 1) {
44407         if (i * 8 + j * 6 > input.length * 8) {
44408           output += b64pad;
44409         } else {
44410           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44411         }
44412       }
44413     }
44414     return output;
44415   }
44416
44417   Hashes = {
44418     /**
44419      * @property {String} version
44420      * @readonly
44421      */
44422     VERSION: '1.0.5',
44423     /**
44424      * @member Hashes
44425      * @class Base64
44426      * @constructor
44427      */
44428     Base64: function() {
44429       // private properties
44430       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
44431         pad = '=', // default pad according with the RFC standard
44432         url = false, // URL encoding support @todo
44433         utf8 = true; // by default enable UTF-8 support encoding
44434
44435       // public method for encoding
44436       this.encode = function(input) {
44437         var i, j, triplet,
44438           output = '',
44439           len = input.length;
44440
44441         pad = pad || '=';
44442         input = (utf8) ? utf8Encode(input) : input;
44443
44444         for (i = 0; i < len; i += 3) {
44445           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
44446           for (j = 0; j < 4; j += 1) {
44447             if (i * 8 + j * 6 > len * 8) {
44448               output += pad;
44449             } else {
44450               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
44451             }
44452           }
44453         }
44454         return output;
44455       };
44456
44457       // public method for decoding
44458       this.decode = function(input) {
44459         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
44460         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
44461           dec = '',
44462           arr = [];
44463         if (!input) {
44464           return input;
44465         }
44466
44467         i = ac = 0;
44468         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
44469         //input += '';
44470
44471         do { // unpack four hexets into three octets using index points in b64
44472           h1 = tab.indexOf(input.charAt(i += 1));
44473           h2 = tab.indexOf(input.charAt(i += 1));
44474           h3 = tab.indexOf(input.charAt(i += 1));
44475           h4 = tab.indexOf(input.charAt(i += 1));
44476
44477           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
44478
44479           o1 = bits >> 16 & 0xff;
44480           o2 = bits >> 8 & 0xff;
44481           o3 = bits & 0xff;
44482           ac += 1;
44483
44484           if (h3 === 64) {
44485             arr[ac] = String.fromCharCode(o1);
44486           } else if (h4 === 64) {
44487             arr[ac] = String.fromCharCode(o1, o2);
44488           } else {
44489             arr[ac] = String.fromCharCode(o1, o2, o3);
44490           }
44491         } while (i < input.length);
44492
44493         dec = arr.join('');
44494         dec = (utf8) ? utf8Decode(dec) : dec;
44495
44496         return dec;
44497       };
44498
44499       // set custom pad string
44500       this.setPad = function(str) {
44501         pad = str || pad;
44502         return this;
44503       };
44504       // set custom tab string characters
44505       this.setTab = function(str) {
44506         tab = str || tab;
44507         return this;
44508       };
44509       this.setUTF8 = function(bool) {
44510         if (typeof bool === 'boolean') {
44511           utf8 = bool;
44512         }
44513         return this;
44514       };
44515     },
44516
44517     /**
44518      * CRC-32 calculation
44519      * @member Hashes
44520      * @method CRC32
44521      * @static
44522      * @param {String} str Input String
44523      * @return {String}
44524      */
44525     CRC32: function(str) {
44526       var crc = 0,
44527         x = 0,
44528         y = 0,
44529         table, i, iTop;
44530       str = utf8Encode(str);
44531
44532       table = [
44533         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44534         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44535         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44536         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44537         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44538         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44539         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44540         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44541         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44542         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44543         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44544         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44545         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44546         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44547         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44548         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44549         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44550         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44551         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44552         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44553         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44554         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44555         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44556         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44557         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44558         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44559       ].join('');
44560
44561       crc = crc ^ (-1);
44562       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44563         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44564         x = '0x' + table.substr(y * 9, 8);
44565         crc = (crc >>> 8) ^ x;
44566       }
44567       // always return a positive number (that's what >>> 0 does)
44568       return (crc ^ (-1)) >>> 0;
44569     },
44570     /**
44571      * @member Hashes
44572      * @class MD5
44573      * @constructor
44574      * @param {Object} [config]
44575      *
44576      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44577      * Digest Algorithm, as defined in RFC 1321.
44578      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44579      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44580      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44581      */
44582     MD5: function(options) {
44583       /**
44584        * Private config properties. You may need to tweak these to be compatible with
44585        * the server-side, but the defaults work in most cases.
44586        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44587        */
44588       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44589         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44590         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44591
44592       // privileged (public) methods
44593       this.hex = function(s) {
44594         return rstr2hex(rstr(s, utf8), hexcase);
44595       };
44596       this.b64 = function(s) {
44597         return rstr2b64(rstr(s), b64pad);
44598       };
44599       this.any = function(s, e) {
44600         return rstr2any(rstr(s, utf8), e);
44601       };
44602       this.raw = function(s) {
44603         return rstr(s, utf8);
44604       };
44605       this.hex_hmac = function(k, d) {
44606         return rstr2hex(rstr_hmac(k, d), hexcase);
44607       };
44608       this.b64_hmac = function(k, d) {
44609         return rstr2b64(rstr_hmac(k, d), b64pad);
44610       };
44611       this.any_hmac = function(k, d, e) {
44612         return rstr2any(rstr_hmac(k, d), e);
44613       };
44614       /**
44615        * Perform a simple self-test to see if the VM is working
44616        * @return {String} Hexadecimal hash sample
44617        */
44618       this.vm_test = function() {
44619         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44620       };
44621       /**
44622        * Enable/disable uppercase hexadecimal returned string
44623        * @param {Boolean}
44624        * @return {Object} this
44625        */
44626       this.setUpperCase = function(a) {
44627         if (typeof a === 'boolean') {
44628           hexcase = a;
44629         }
44630         return this;
44631       };
44632       /**
44633        * Defines a base64 pad string
44634        * @param {String} Pad
44635        * @return {Object} this
44636        */
44637       this.setPad = function(a) {
44638         b64pad = a || b64pad;
44639         return this;
44640       };
44641       /**
44642        * Defines a base64 pad string
44643        * @param {Boolean}
44644        * @return {Object} [this]
44645        */
44646       this.setUTF8 = function(a) {
44647         if (typeof a === 'boolean') {
44648           utf8 = a;
44649         }
44650         return this;
44651       };
44652
44653       // private methods
44654
44655       /**
44656        * Calculate the MD5 of a raw string
44657        */
44658
44659       function rstr(s) {
44660         s = (utf8) ? utf8Encode(s) : s;
44661         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44662       }
44663
44664       /**
44665        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44666        */
44667
44668       function rstr_hmac(key, data) {
44669         var bkey, ipad, opad, hash, i;
44670
44671         key = (utf8) ? utf8Encode(key) : key;
44672         data = (utf8) ? utf8Encode(data) : data;
44673         bkey = rstr2binl(key);
44674         if (bkey.length > 16) {
44675           bkey = binl(bkey, key.length * 8);
44676         }
44677
44678         ipad = Array(16), opad = Array(16);
44679         for (i = 0; i < 16; i += 1) {
44680           ipad[i] = bkey[i] ^ 0x36363636;
44681           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44682         }
44683         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44684         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44685       }
44686
44687       /**
44688        * Calculate the MD5 of an array of little-endian words, and a bit length.
44689        */
44690
44691       function binl(x, len) {
44692         var i, olda, oldb, oldc, oldd,
44693           a = 1732584193,
44694           b = -271733879,
44695           c = -1732584194,
44696           d = 271733878;
44697
44698         /* append padding */
44699         x[len >> 5] |= 0x80 << ((len) % 32);
44700         x[(((len + 64) >>> 9) << 4) + 14] = len;
44701
44702         for (i = 0; i < x.length; i += 16) {
44703           olda = a;
44704           oldb = b;
44705           oldc = c;
44706           oldd = d;
44707
44708           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44709           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44710           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44711           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44712           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44713           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44714           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44715           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44716           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44717           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44718           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44719           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44720           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44721           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44722           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44723           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44724
44725           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44726           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44727           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44728           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44729           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44730           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44731           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44732           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44733           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44734           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44735           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44736           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44737           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44738           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44739           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44740           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44741
44742           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44743           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44744           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44745           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44746           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44747           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44748           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44749           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44750           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44751           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44752           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44753           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44754           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44755           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44756           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44757           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44758
44759           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44760           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44761           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44762           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44763           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44764           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44765           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44766           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44767           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44768           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44769           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44770           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44771           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44772           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44773           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44774           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44775
44776           a = safe_add(a, olda);
44777           b = safe_add(b, oldb);
44778           c = safe_add(c, oldc);
44779           d = safe_add(d, oldd);
44780         }
44781         return Array(a, b, c, d);
44782       }
44783
44784       /**
44785        * These functions implement the four basic operations the algorithm uses.
44786        */
44787
44788       function md5_cmn(q, a, b, x, s, t) {
44789         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44790       }
44791
44792       function md5_ff(a, b, c, d, x, s, t) {
44793         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44794       }
44795
44796       function md5_gg(a, b, c, d, x, s, t) {
44797         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44798       }
44799
44800       function md5_hh(a, b, c, d, x, s, t) {
44801         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44802       }
44803
44804       function md5_ii(a, b, c, d, x, s, t) {
44805         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44806       }
44807     },
44808     /**
44809      * @member Hashes
44810      * @class Hashes.SHA1
44811      * @param {Object} [config]
44812      * @constructor
44813      *
44814      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44815      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44816      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44817      * See http://pajhome.org.uk/crypt/md5 for details.
44818      */
44819     SHA1: function(options) {
44820       /**
44821        * Private config properties. You may need to tweak these to be compatible with
44822        * the server-side, but the defaults work in most cases.
44823        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44824        */
44825       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44826         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44827         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44828
44829       // public methods
44830       this.hex = function(s) {
44831         return rstr2hex(rstr(s, utf8), hexcase);
44832       };
44833       this.b64 = function(s) {
44834         return rstr2b64(rstr(s, utf8), b64pad);
44835       };
44836       this.any = function(s, e) {
44837         return rstr2any(rstr(s, utf8), e);
44838       };
44839       this.raw = function(s) {
44840         return rstr(s, utf8);
44841       };
44842       this.hex_hmac = function(k, d) {
44843         return rstr2hex(rstr_hmac(k, d));
44844       };
44845       this.b64_hmac = function(k, d) {
44846         return rstr2b64(rstr_hmac(k, d), b64pad);
44847       };
44848       this.any_hmac = function(k, d, e) {
44849         return rstr2any(rstr_hmac(k, d), e);
44850       };
44851       /**
44852        * Perform a simple self-test to see if the VM is working
44853        * @return {String} Hexadecimal hash sample
44854        * @public
44855        */
44856       this.vm_test = function() {
44857         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44858       };
44859       /**
44860        * @description Enable/disable uppercase hexadecimal returned string
44861        * @param {boolean}
44862        * @return {Object} this
44863        * @public
44864        */
44865       this.setUpperCase = function(a) {
44866         if (typeof a === 'boolean') {
44867           hexcase = a;
44868         }
44869         return this;
44870       };
44871       /**
44872        * @description Defines a base64 pad string
44873        * @param {string} Pad
44874        * @return {Object} this
44875        * @public
44876        */
44877       this.setPad = function(a) {
44878         b64pad = a || b64pad;
44879         return this;
44880       };
44881       /**
44882        * @description Defines a base64 pad string
44883        * @param {boolean}
44884        * @return {Object} this
44885        * @public
44886        */
44887       this.setUTF8 = function(a) {
44888         if (typeof a === 'boolean') {
44889           utf8 = a;
44890         }
44891         return this;
44892       };
44893
44894       // private methods
44895
44896       /**
44897        * Calculate the SHA-512 of a raw string
44898        */
44899
44900       function rstr(s) {
44901         s = (utf8) ? utf8Encode(s) : s;
44902         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44903       }
44904
44905       /**
44906        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44907        */
44908
44909       function rstr_hmac(key, data) {
44910         var bkey, ipad, opad, i, hash;
44911         key = (utf8) ? utf8Encode(key) : key;
44912         data = (utf8) ? utf8Encode(data) : data;
44913         bkey = rstr2binb(key);
44914
44915         if (bkey.length > 16) {
44916           bkey = binb(bkey, key.length * 8);
44917         }
44918         ipad = Array(16), opad = Array(16);
44919         for (i = 0; i < 16; i += 1) {
44920           ipad[i] = bkey[i] ^ 0x36363636;
44921           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44922         }
44923         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44924         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44925       }
44926
44927       /**
44928        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44929        */
44930
44931       function binb(x, len) {
44932         var i, j, t, olda, oldb, oldc, oldd, olde,
44933           w = Array(80),
44934           a = 1732584193,
44935           b = -271733879,
44936           c = -1732584194,
44937           d = 271733878,
44938           e = -1009589776;
44939
44940         /* append padding */
44941         x[len >> 5] |= 0x80 << (24 - len % 32);
44942         x[((len + 64 >> 9) << 4) + 15] = len;
44943
44944         for (i = 0; i < x.length; i += 16) {
44945           olda = a,
44946           oldb = b;
44947           oldc = c;
44948           oldd = d;
44949           olde = e;
44950
44951           for (j = 0; j < 80; j += 1) {
44952             if (j < 16) {
44953               w[j] = x[i + j];
44954             } else {
44955               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
44956             }
44957             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
44958               safe_add(safe_add(e, w[j]), sha1_kt(j)));
44959             e = d;
44960             d = c;
44961             c = bit_rol(b, 30);
44962             b = a;
44963             a = t;
44964           }
44965
44966           a = safe_add(a, olda);
44967           b = safe_add(b, oldb);
44968           c = safe_add(c, oldc);
44969           d = safe_add(d, oldd);
44970           e = safe_add(e, olde);
44971         }
44972         return Array(a, b, c, d, e);
44973       }
44974
44975       /**
44976        * Perform the appropriate triplet combination function for the current
44977        * iteration
44978        */
44979
44980       function sha1_ft(t, b, c, d) {
44981         if (t < 20) {
44982           return (b & c) | ((~b) & d);
44983         }
44984         if (t < 40) {
44985           return b ^ c ^ d;
44986         }
44987         if (t < 60) {
44988           return (b & c) | (b & d) | (c & d);
44989         }
44990         return b ^ c ^ d;
44991       }
44992
44993       /**
44994        * Determine the appropriate additive constant for the current iteration
44995        */
44996
44997       function sha1_kt(t) {
44998         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
44999           (t < 60) ? -1894007588 : -899497514;
45000       }
45001     },
45002     /**
45003      * @class Hashes.SHA256
45004      * @param {config}
45005      *
45006      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
45007      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
45008      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45009      * See http://pajhome.org.uk/crypt/md5 for details.
45010      * Also http://anmar.eu.org/projects/jssha2/
45011      */
45012     SHA256: function(options) {
45013       /**
45014        * Private properties configuration variables. You may need to tweak these to be compatible with
45015        * the server-side, but the defaults work in most cases.
45016        * @see this.setUpperCase() method
45017        * @see this.setPad() method
45018        */
45019       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
45020         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45021         /* base-64 pad character. Default '=' for strict RFC compliance   */
45022         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45023         /* enable/disable utf8 encoding */
45024         sha256_K;
45025
45026       /* privileged (public) methods */
45027       this.hex = function(s) {
45028         return rstr2hex(rstr(s, utf8));
45029       };
45030       this.b64 = function(s) {
45031         return rstr2b64(rstr(s, utf8), b64pad);
45032       };
45033       this.any = function(s, e) {
45034         return rstr2any(rstr(s, utf8), e);
45035       };
45036       this.raw = function(s) {
45037         return rstr(s, utf8);
45038       };
45039       this.hex_hmac = function(k, d) {
45040         return rstr2hex(rstr_hmac(k, d));
45041       };
45042       this.b64_hmac = function(k, d) {
45043         return rstr2b64(rstr_hmac(k, d), b64pad);
45044       };
45045       this.any_hmac = function(k, d, e) {
45046         return rstr2any(rstr_hmac(k, d), e);
45047       };
45048       /**
45049        * Perform a simple self-test to see if the VM is working
45050        * @return {String} Hexadecimal hash sample
45051        * @public
45052        */
45053       this.vm_test = function() {
45054         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45055       };
45056       /**
45057        * Enable/disable uppercase hexadecimal returned string
45058        * @param {boolean}
45059        * @return {Object} this
45060        * @public
45061        */
45062       this.setUpperCase = function(a) {
45063         if (typeof a === 'boolean') {
45064           hexcase = a;
45065         }
45066         return this;
45067       };
45068       /**
45069        * @description Defines a base64 pad string
45070        * @param {string} Pad
45071        * @return {Object} this
45072        * @public
45073        */
45074       this.setPad = function(a) {
45075         b64pad = a || b64pad;
45076         return this;
45077       };
45078       /**
45079        * Defines a base64 pad string
45080        * @param {boolean}
45081        * @return {Object} this
45082        * @public
45083        */
45084       this.setUTF8 = function(a) {
45085         if (typeof a === 'boolean') {
45086           utf8 = a;
45087         }
45088         return this;
45089       };
45090
45091       // private methods
45092
45093       /**
45094        * Calculate the SHA-512 of a raw string
45095        */
45096
45097       function rstr(s, utf8) {
45098         s = (utf8) ? utf8Encode(s) : s;
45099         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45100       }
45101
45102       /**
45103        * Calculate the HMAC-sha256 of a key and some data (raw strings)
45104        */
45105
45106       function rstr_hmac(key, data) {
45107         key = (utf8) ? utf8Encode(key) : key;
45108         data = (utf8) ? utf8Encode(data) : data;
45109         var hash, i = 0,
45110           bkey = rstr2binb(key),
45111           ipad = Array(16),
45112           opad = Array(16);
45113
45114         if (bkey.length > 16) {
45115           bkey = binb(bkey, key.length * 8);
45116         }
45117
45118         for (; i < 16; i += 1) {
45119           ipad[i] = bkey[i] ^ 0x36363636;
45120           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45121         }
45122
45123         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
45124         return binb2rstr(binb(opad.concat(hash), 512 + 256));
45125       }
45126
45127       /*
45128        * Main sha256 function, with its support functions
45129        */
45130
45131       function sha256_S(X, n) {
45132         return (X >>> n) | (X << (32 - n));
45133       }
45134
45135       function sha256_R(X, n) {
45136         return (X >>> n);
45137       }
45138
45139       function sha256_Ch(x, y, z) {
45140         return ((x & y) ^ ((~x) & z));
45141       }
45142
45143       function sha256_Maj(x, y, z) {
45144         return ((x & y) ^ (x & z) ^ (y & z));
45145       }
45146
45147       function sha256_Sigma0256(x) {
45148         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
45149       }
45150
45151       function sha256_Sigma1256(x) {
45152         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
45153       }
45154
45155       function sha256_Gamma0256(x) {
45156         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
45157       }
45158
45159       function sha256_Gamma1256(x) {
45160         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
45161       }
45162
45163       sha256_K = [
45164         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
45165         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
45166         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
45167         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
45168         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
45169         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
45170         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
45171       ];
45172
45173       function binb(m, l) {
45174         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
45175           1359893119, -1694144372, 528734635, 1541459225
45176         ];
45177         var W = new Array(64);
45178         var a, b, c, d, e, f, g, h;
45179         var i, j, T1, T2;
45180
45181         /* append padding */
45182         m[l >> 5] |= 0x80 << (24 - l % 32);
45183         m[((l + 64 >> 9) << 4) + 15] = l;
45184
45185         for (i = 0; i < m.length; i += 16) {
45186           a = HASH[0];
45187           b = HASH[1];
45188           c = HASH[2];
45189           d = HASH[3];
45190           e = HASH[4];
45191           f = HASH[5];
45192           g = HASH[6];
45193           h = HASH[7];
45194
45195           for (j = 0; j < 64; j += 1) {
45196             if (j < 16) {
45197               W[j] = m[j + i];
45198             } else {
45199               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
45200                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
45201             }
45202
45203             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
45204               sha256_K[j]), W[j]);
45205             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
45206             h = g;
45207             g = f;
45208             f = e;
45209             e = safe_add(d, T1);
45210             d = c;
45211             c = b;
45212             b = a;
45213             a = safe_add(T1, T2);
45214           }
45215
45216           HASH[0] = safe_add(a, HASH[0]);
45217           HASH[1] = safe_add(b, HASH[1]);
45218           HASH[2] = safe_add(c, HASH[2]);
45219           HASH[3] = safe_add(d, HASH[3]);
45220           HASH[4] = safe_add(e, HASH[4]);
45221           HASH[5] = safe_add(f, HASH[5]);
45222           HASH[6] = safe_add(g, HASH[6]);
45223           HASH[7] = safe_add(h, HASH[7]);
45224         }
45225         return HASH;
45226       }
45227
45228     },
45229
45230     /**
45231      * @class Hashes.SHA512
45232      * @param {config}
45233      *
45234      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
45235      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
45236      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45237      * See http://pajhome.org.uk/crypt/md5 for details.
45238      */
45239     SHA512: function(options) {
45240       /**
45241        * Private properties configuration variables. You may need to tweak these to be compatible with
45242        * the server-side, but the defaults work in most cases.
45243        * @see this.setUpperCase() method
45244        * @see this.setPad() method
45245        */
45246       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45247         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45248         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45249         /* base-64 pad character. Default '=' for strict RFC compliance   */
45250         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45251         /* enable/disable utf8 encoding */
45252         sha512_k;
45253
45254       /* privileged (public) methods */
45255       this.hex = function(s) {
45256         return rstr2hex(rstr(s));
45257       };
45258       this.b64 = function(s) {
45259         return rstr2b64(rstr(s), b64pad);
45260       };
45261       this.any = function(s, e) {
45262         return rstr2any(rstr(s), e);
45263       };
45264       this.raw = function(s) {
45265         return rstr(s, utf8);
45266       };
45267       this.hex_hmac = function(k, d) {
45268         return rstr2hex(rstr_hmac(k, d));
45269       };
45270       this.b64_hmac = function(k, d) {
45271         return rstr2b64(rstr_hmac(k, d), b64pad);
45272       };
45273       this.any_hmac = function(k, d, e) {
45274         return rstr2any(rstr_hmac(k, d), e);
45275       };
45276       /**
45277        * Perform a simple self-test to see if the VM is working
45278        * @return {String} Hexadecimal hash sample
45279        * @public
45280        */
45281       this.vm_test = function() {
45282         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45283       };
45284       /**
45285        * @description Enable/disable uppercase hexadecimal returned string
45286        * @param {boolean}
45287        * @return {Object} this
45288        * @public
45289        */
45290       this.setUpperCase = function(a) {
45291         if (typeof a === 'boolean') {
45292           hexcase = a;
45293         }
45294         return this;
45295       };
45296       /**
45297        * @description Defines a base64 pad string
45298        * @param {string} Pad
45299        * @return {Object} this
45300        * @public
45301        */
45302       this.setPad = function(a) {
45303         b64pad = a || b64pad;
45304         return this;
45305       };
45306       /**
45307        * @description Defines a base64 pad string
45308        * @param {boolean}
45309        * @return {Object} this
45310        * @public
45311        */
45312       this.setUTF8 = function(a) {
45313         if (typeof a === 'boolean') {
45314           utf8 = a;
45315         }
45316         return this;
45317       };
45318
45319       /* private methods */
45320
45321       /**
45322        * Calculate the SHA-512 of a raw string
45323        */
45324
45325       function rstr(s) {
45326         s = (utf8) ? utf8Encode(s) : s;
45327         return binb2rstr(binb(rstr2binb(s), s.length * 8));
45328       }
45329       /*
45330        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
45331        */
45332
45333       function rstr_hmac(key, data) {
45334         key = (utf8) ? utf8Encode(key) : key;
45335         data = (utf8) ? utf8Encode(data) : data;
45336
45337         var hash, i = 0,
45338           bkey = rstr2binb(key),
45339           ipad = Array(32),
45340           opad = Array(32);
45341
45342         if (bkey.length > 32) {
45343           bkey = binb(bkey, key.length * 8);
45344         }
45345
45346         for (; i < 32; i += 1) {
45347           ipad[i] = bkey[i] ^ 0x36363636;
45348           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45349         }
45350
45351         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
45352         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
45353       }
45354
45355       /**
45356        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
45357        */
45358
45359       function binb(x, len) {
45360         var j, i, l,
45361           W = new Array(80),
45362           hash = new Array(16),
45363           //Initial hash values
45364           H = [
45365             new int64(0x6a09e667, -205731576),
45366             new int64(-1150833019, -2067093701),
45367             new int64(0x3c6ef372, -23791573),
45368             new int64(-1521486534, 0x5f1d36f1),
45369             new int64(0x510e527f, -1377402159),
45370             new int64(-1694144372, 0x2b3e6c1f),
45371             new int64(0x1f83d9ab, -79577749),
45372             new int64(0x5be0cd19, 0x137e2179)
45373           ],
45374           T1 = new int64(0, 0),
45375           T2 = new int64(0, 0),
45376           a = new int64(0, 0),
45377           b = new int64(0, 0),
45378           c = new int64(0, 0),
45379           d = new int64(0, 0),
45380           e = new int64(0, 0),
45381           f = new int64(0, 0),
45382           g = new int64(0, 0),
45383           h = new int64(0, 0),
45384           //Temporary variables not specified by the document
45385           s0 = new int64(0, 0),
45386           s1 = new int64(0, 0),
45387           Ch = new int64(0, 0),
45388           Maj = new int64(0, 0),
45389           r1 = new int64(0, 0),
45390           r2 = new int64(0, 0),
45391           r3 = new int64(0, 0);
45392
45393         if (sha512_k === undefined) {
45394           //SHA512 constants
45395           sha512_k = [
45396             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
45397             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
45398             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
45399             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
45400             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
45401             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
45402             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
45403             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
45404             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
45405             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
45406             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
45407             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
45408             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
45409             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
45410             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
45411             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
45412             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
45413             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
45414             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
45415             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
45416             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
45417             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
45418             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
45419             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
45420             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
45421             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
45422             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
45423             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
45424             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
45425             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
45426             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
45427             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
45428             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
45429             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
45430             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
45431             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
45432             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
45433             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
45434             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
45435             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
45436           ];
45437         }
45438
45439         for (i = 0; i < 80; i += 1) {
45440           W[i] = new int64(0, 0);
45441         }
45442
45443         // append padding to the source string. The format is described in the FIPS.
45444         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
45445         x[((len + 128 >> 10) << 5) + 31] = len;
45446         l = x.length;
45447         for (i = 0; i < l; i += 32) { //32 dwords is the block size
45448           int64copy(a, H[0]);
45449           int64copy(b, H[1]);
45450           int64copy(c, H[2]);
45451           int64copy(d, H[3]);
45452           int64copy(e, H[4]);
45453           int64copy(f, H[5]);
45454           int64copy(g, H[6]);
45455           int64copy(h, H[7]);
45456
45457           for (j = 0; j < 16; j += 1) {
45458             W[j].h = x[i + 2 * j];
45459             W[j].l = x[i + 2 * j + 1];
45460           }
45461
45462           for (j = 16; j < 80; j += 1) {
45463             //sigma1
45464             int64rrot(r1, W[j - 2], 19);
45465             int64revrrot(r2, W[j - 2], 29);
45466             int64shr(r3, W[j - 2], 6);
45467             s1.l = r1.l ^ r2.l ^ r3.l;
45468             s1.h = r1.h ^ r2.h ^ r3.h;
45469             //sigma0
45470             int64rrot(r1, W[j - 15], 1);
45471             int64rrot(r2, W[j - 15], 8);
45472             int64shr(r3, W[j - 15], 7);
45473             s0.l = r1.l ^ r2.l ^ r3.l;
45474             s0.h = r1.h ^ r2.h ^ r3.h;
45475
45476             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
45477           }
45478
45479           for (j = 0; j < 80; j += 1) {
45480             //Ch
45481             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45482             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45483
45484             //Sigma1
45485             int64rrot(r1, e, 14);
45486             int64rrot(r2, e, 18);
45487             int64revrrot(r3, e, 9);
45488             s1.l = r1.l ^ r2.l ^ r3.l;
45489             s1.h = r1.h ^ r2.h ^ r3.h;
45490
45491             //Sigma0
45492             int64rrot(r1, a, 28);
45493             int64revrrot(r2, a, 2);
45494             int64revrrot(r3, a, 7);
45495             s0.l = r1.l ^ r2.l ^ r3.l;
45496             s0.h = r1.h ^ r2.h ^ r3.h;
45497
45498             //Maj
45499             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45500             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45501
45502             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45503             int64add(T2, s0, Maj);
45504
45505             int64copy(h, g);
45506             int64copy(g, f);
45507             int64copy(f, e);
45508             int64add(e, d, T1);
45509             int64copy(d, c);
45510             int64copy(c, b);
45511             int64copy(b, a);
45512             int64add(a, T1, T2);
45513           }
45514           int64add(H[0], H[0], a);
45515           int64add(H[1], H[1], b);
45516           int64add(H[2], H[2], c);
45517           int64add(H[3], H[3], d);
45518           int64add(H[4], H[4], e);
45519           int64add(H[5], H[5], f);
45520           int64add(H[6], H[6], g);
45521           int64add(H[7], H[7], h);
45522         }
45523
45524         //represent the hash as an array of 32-bit dwords
45525         for (i = 0; i < 8; i += 1) {
45526           hash[2 * i] = H[i].h;
45527           hash[2 * i + 1] = H[i].l;
45528         }
45529         return hash;
45530       }
45531
45532       //A constructor for 64-bit numbers
45533
45534       function int64(h, l) {
45535         this.h = h;
45536         this.l = l;
45537         //this.toString = int64toString;
45538       }
45539
45540       //Copies src into dst, assuming both are 64-bit numbers
45541
45542       function int64copy(dst, src) {
45543         dst.h = src.h;
45544         dst.l = src.l;
45545       }
45546
45547       //Right-rotates a 64-bit number by shift
45548       //Won't handle cases of shift>=32
45549       //The function revrrot() is for that
45550
45551       function int64rrot(dst, x, shift) {
45552         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45553         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45554       }
45555
45556       //Reverses the dwords of the source and then rotates right by shift.
45557       //This is equivalent to rotation by 32+shift
45558
45559       function int64revrrot(dst, x, shift) {
45560         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45561         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45562       }
45563
45564       //Bitwise-shifts right a 64-bit number by shift
45565       //Won't handle shift>=32, but it's never needed in SHA512
45566
45567       function int64shr(dst, x, shift) {
45568         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45569         dst.h = (x.h >>> shift);
45570       }
45571
45572       //Adds two 64-bit numbers
45573       //Like the original implementation, does not rely on 32-bit operations
45574
45575       function int64add(dst, x, y) {
45576         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45577         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45578         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45579         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45580         dst.l = (w0 & 0xffff) | (w1 << 16);
45581         dst.h = (w2 & 0xffff) | (w3 << 16);
45582       }
45583
45584       //Same, except with 4 addends. Works faster than adding them one by one.
45585
45586       function int64add4(dst, a, b, c, d) {
45587         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45588         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45589         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45590         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45591         dst.l = (w0 & 0xffff) | (w1 << 16);
45592         dst.h = (w2 & 0xffff) | (w3 << 16);
45593       }
45594
45595       //Same, except with 5 addends
45596
45597       function int64add5(dst, a, b, c, d, e) {
45598         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45599           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45600           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45601           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45602         dst.l = (w0 & 0xffff) | (w1 << 16);
45603         dst.h = (w2 & 0xffff) | (w3 << 16);
45604       }
45605     },
45606     /**
45607      * @class Hashes.RMD160
45608      * @constructor
45609      * @param {Object} [config]
45610      *
45611      * A JavaScript implementation of the RIPEMD-160 Algorithm
45612      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45613      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45614      * See http://pajhome.org.uk/crypt/md5 for details.
45615      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45616      */
45617     RMD160: function(options) {
45618       /**
45619        * Private properties configuration variables. You may need to tweak these to be compatible with
45620        * the server-side, but the defaults work in most cases.
45621        * @see this.setUpperCase() method
45622        * @see this.setPad() method
45623        */
45624       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45625         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45626         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45627         /* base-64 pad character. Default '=' for strict RFC compliance   */
45628         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45629         /* enable/disable utf8 encoding */
45630         rmd160_r1 = [
45631           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45632           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45633           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45634           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45635           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45636         ],
45637         rmd160_r2 = [
45638           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45639           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45640           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45641           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45642           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45643         ],
45644         rmd160_s1 = [
45645           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45646           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45647           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45648           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45649           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45650         ],
45651         rmd160_s2 = [
45652           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45653           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45654           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45655           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45656           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45657         ];
45658
45659       /* privileged (public) methods */
45660       this.hex = function(s) {
45661         return rstr2hex(rstr(s, utf8));
45662       };
45663       this.b64 = function(s) {
45664         return rstr2b64(rstr(s, utf8), b64pad);
45665       };
45666       this.any = function(s, e) {
45667         return rstr2any(rstr(s, utf8), e);
45668       };
45669       this.raw = function(s) {
45670         return rstr(s, utf8);
45671       };
45672       this.hex_hmac = function(k, d) {
45673         return rstr2hex(rstr_hmac(k, d));
45674       };
45675       this.b64_hmac = function(k, d) {
45676         return rstr2b64(rstr_hmac(k, d), b64pad);
45677       };
45678       this.any_hmac = function(k, d, e) {
45679         return rstr2any(rstr_hmac(k, d), e);
45680       };
45681       /**
45682        * Perform a simple self-test to see if the VM is working
45683        * @return {String} Hexadecimal hash sample
45684        * @public
45685        */
45686       this.vm_test = function() {
45687         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45688       };
45689       /**
45690        * @description Enable/disable uppercase hexadecimal returned string
45691        * @param {boolean}
45692        * @return {Object} this
45693        * @public
45694        */
45695       this.setUpperCase = function(a) {
45696         if (typeof a === 'boolean') {
45697           hexcase = a;
45698         }
45699         return this;
45700       };
45701       /**
45702        * @description Defines a base64 pad string
45703        * @param {string} Pad
45704        * @return {Object} this
45705        * @public
45706        */
45707       this.setPad = function(a) {
45708         if (typeof a !== 'undefined') {
45709           b64pad = a;
45710         }
45711         return this;
45712       };
45713       /**
45714        * @description Defines a base64 pad string
45715        * @param {boolean}
45716        * @return {Object} this
45717        * @public
45718        */
45719       this.setUTF8 = function(a) {
45720         if (typeof a === 'boolean') {
45721           utf8 = a;
45722         }
45723         return this;
45724       };
45725
45726       /* private methods */
45727
45728       /**
45729        * Calculate the rmd160 of a raw string
45730        */
45731
45732       function rstr(s) {
45733         s = (utf8) ? utf8Encode(s) : s;
45734         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45735       }
45736
45737       /**
45738        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45739        */
45740
45741       function rstr_hmac(key, data) {
45742         key = (utf8) ? utf8Encode(key) : key;
45743         data = (utf8) ? utf8Encode(data) : data;
45744         var i, hash,
45745           bkey = rstr2binl(key),
45746           ipad = Array(16),
45747           opad = Array(16);
45748
45749         if (bkey.length > 16) {
45750           bkey = binl(bkey, key.length * 8);
45751         }
45752
45753         for (i = 0; i < 16; i += 1) {
45754           ipad[i] = bkey[i] ^ 0x36363636;
45755           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45756         }
45757         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45758         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45759       }
45760
45761       /**
45762        * Convert an array of little-endian words to a string
45763        */
45764
45765       function binl2rstr(input) {
45766         var i, output = '',
45767           l = input.length * 32;
45768         for (i = 0; i < l; i += 8) {
45769           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45770         }
45771         return output;
45772       }
45773
45774       /**
45775        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45776        */
45777
45778       function binl(x, len) {
45779         var T, j, i, l,
45780           h0 = 0x67452301,
45781           h1 = 0xefcdab89,
45782           h2 = 0x98badcfe,
45783           h3 = 0x10325476,
45784           h4 = 0xc3d2e1f0,
45785           A1, B1, C1, D1, E1,
45786           A2, B2, C2, D2, E2;
45787
45788         /* append padding */
45789         x[len >> 5] |= 0x80 << (len % 32);
45790         x[(((len + 64) >>> 9) << 4) + 14] = len;
45791         l = x.length;
45792
45793         for (i = 0; i < l; i += 16) {
45794           A1 = A2 = h0;
45795           B1 = B2 = h1;
45796           C1 = C2 = h2;
45797           D1 = D2 = h3;
45798           E1 = E2 = h4;
45799           for (j = 0; j <= 79; j += 1) {
45800             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45801             T = safe_add(T, x[i + rmd160_r1[j]]);
45802             T = safe_add(T, rmd160_K1(j));
45803             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45804             A1 = E1;
45805             E1 = D1;
45806             D1 = bit_rol(C1, 10);
45807             C1 = B1;
45808             B1 = T;
45809             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45810             T = safe_add(T, x[i + rmd160_r2[j]]);
45811             T = safe_add(T, rmd160_K2(j));
45812             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45813             A2 = E2;
45814             E2 = D2;
45815             D2 = bit_rol(C2, 10);
45816             C2 = B2;
45817             B2 = T;
45818           }
45819
45820           T = safe_add(h1, safe_add(C1, D2));
45821           h1 = safe_add(h2, safe_add(D1, E2));
45822           h2 = safe_add(h3, safe_add(E1, A2));
45823           h3 = safe_add(h4, safe_add(A1, B2));
45824           h4 = safe_add(h0, safe_add(B1, C2));
45825           h0 = T;
45826         }
45827         return [h0, h1, h2, h3, h4];
45828       }
45829
45830       // specific algorithm methods
45831
45832       function rmd160_f(j, x, y, z) {
45833         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45834           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45835           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45836           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45837           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45838           'rmd160_f: j out of range';
45839       }
45840
45841       function rmd160_K1(j) {
45842         return (0 <= j && j <= 15) ? 0x00000000 :
45843           (16 <= j && j <= 31) ? 0x5a827999 :
45844           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45845           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45846           (64 <= j && j <= 79) ? 0xa953fd4e :
45847           'rmd160_K1: j out of range';
45848       }
45849
45850       function rmd160_K2(j) {
45851         return (0 <= j && j <= 15) ? 0x50a28be6 :
45852           (16 <= j && j <= 31) ? 0x5c4dd124 :
45853           (32 <= j && j <= 47) ? 0x6d703ef3 :
45854           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45855           (64 <= j && j <= 79) ? 0x00000000 :
45856           'rmd160_K2: j out of range';
45857       }
45858     }
45859   };
45860
45861   // exposes Hashes
45862   (function(window, undefined) {
45863     var freeExports = false;
45864     {
45865       freeExports = exports;
45866       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45867         window = commonjsGlobal;
45868       }
45869     }
45870
45871     if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
45872       // define as an anonymous module, so, through path mapping, it can be aliased
45873       undefined(function() {
45874         return Hashes;
45875       });
45876     } else if (freeExports) {
45877       // in Node.js or RingoJS v0.8.0+
45878       if ('object' === 'object' && module && module.exports === freeExports) {
45879         module.exports = Hashes;
45880       }
45881       // in Narwhal or RingoJS v0.7.0-
45882       else {
45883         freeExports.Hashes = Hashes;
45884       }
45885     } else {
45886       // in a browser or Rhino
45887       window.Hashes = Hashes;
45888     }
45889   }(this));
45890 }()); // IIFE
45891 });
45892
45893 var immutable = extend$2;
45894
45895 var hasOwnProperty = Object.prototype.hasOwnProperty;
45896
45897 function extend$2() {
45898     var target = {};
45899
45900     for (var i = 0; i < arguments.length; i++) {
45901         var source = arguments[i];
45902
45903         for (var key in source) {
45904             if (hasOwnProperty.call(source, key)) {
45905                 target[key] = source[key];
45906             }
45907         }
45908     }
45909
45910     return target
45911 }
45912
45913 var hashes = hashes$1;
45914 var xtend$1 = immutable;
45915 var sha1 = new hashes.SHA1();
45916
45917 var ohauth$1 = {};
45918
45919 ohauth$1.qsString = function(obj) {
45920     return Object.keys(obj).sort().map(function(key) {
45921         return ohauth$1.percentEncode(key) + '=' +
45922             ohauth$1.percentEncode(obj[key]);
45923     }).join('&');
45924 };
45925
45926 ohauth$1.stringQs = function(str) {
45927     return str.split('&').filter(function (pair) {
45928         return pair !== '';
45929     }).reduce(function(obj, pair){
45930         var parts = pair.split('=');
45931         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45932             '' : decodeURIComponent(parts[1]);
45933         return obj;
45934     }, {});
45935 };
45936
45937 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45938     var xhr = new XMLHttpRequest(),
45939         twoHundred = /^20\d$/;
45940     xhr.onreadystatechange = function() {
45941         if (4 === xhr.readyState && 0 !== xhr.status) {
45942             if (twoHundred.test(xhr.status)) callback(null, xhr);
45943             else return callback(xhr, null);
45944         }
45945     };
45946     xhr.onerror = function(e) { return callback(e, null); };
45947     xhr.open(method, url, true);
45948     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45949     xhr.send(data);
45950     return xhr;
45951 };
45952
45953 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
45954     var headers = (options && options.header) || {
45955         'Content-Type': 'application/x-www-form-urlencoded'
45956     };
45957     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
45958     return ohauth$1.rawxhr(method, url, data, headers, callback);
45959 };
45960
45961 ohauth$1.nonce = function() {
45962     for (var o = ''; o.length < 6;) {
45963         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
45964     }
45965     return o;
45966 };
45967
45968 ohauth$1.authHeader = function(obj) {
45969     return Object.keys(obj).sort().map(function(key) {
45970         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
45971     }).join(', ');
45972 };
45973
45974 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
45975
45976 ohauth$1.percentEncode = function(s) {
45977     return encodeURIComponent(s)
45978         .replace(/\!/g, '%21').replace(/\'/g, '%27')
45979         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
45980 };
45981
45982 ohauth$1.baseString = function(method, url, params) {
45983     if (params.oauth_signature) delete params.oauth_signature;
45984     return [
45985         method,
45986         ohauth$1.percentEncode(url),
45987         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
45988 };
45989
45990 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
45991     return sha1.b64_hmac(
45992         ohauth$1.percentEncode(oauth_secret) + '&' +
45993         ohauth$1.percentEncode(token_secret),
45994         baseString);
45995 };
45996
45997 /**
45998  * Takes an options object for configuration (consumer_key,
45999  * consumer_secret, version, signature_method, token, token_secret)
46000  * and returns a function that generates the Authorization header
46001  * for given data.
46002  *
46003  * The returned function takes these parameters:
46004  * - method: GET/POST/...
46005  * - uri: full URI with protocol, port, path and query string
46006  * - extra_params: any extra parameters (that are passed in the POST data),
46007  *   can be an object or a from-urlencoded string.
46008  *
46009  * Returned function returns full OAuth header with "OAuth" string in it.
46010  */
46011
46012 ohauth$1.headerGenerator = function(options) {
46013     options = options || {};
46014     var consumer_key = options.consumer_key || '',
46015         consumer_secret = options.consumer_secret || '',
46016         signature_method = options.signature_method || 'HMAC-SHA1',
46017         version = options.version || '1.0',
46018         token = options.token || '',
46019         token_secret = options.token_secret || '';
46020
46021     return function(method, uri, extra_params) {
46022         method = method.toUpperCase();
46023         if (typeof extra_params === 'string' && extra_params.length > 0) {
46024             extra_params = ohauth$1.stringQs(extra_params);
46025         }
46026
46027         var uri_parts = uri.split('?', 2),
46028         base_uri = uri_parts[0];
46029
46030         var query_params = uri_parts.length === 2 ?
46031             ohauth$1.stringQs(uri_parts[1]) : {};
46032
46033         var oauth_params = {
46034             oauth_consumer_key: consumer_key,
46035             oauth_signature_method: signature_method,
46036             oauth_version: version,
46037             oauth_timestamp: ohauth$1.timestamp(),
46038             oauth_nonce: ohauth$1.nonce()
46039         };
46040
46041         if (token) oauth_params.oauth_token = token;
46042
46043         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
46044             base_str = ohauth$1.baseString(method, base_uri, all_params);
46045
46046         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
46047
46048         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
46049     };
46050 };
46051
46052 var index$13 = ohauth$1;
46053
46054 var store$1 = createCommonjsModule(function (module, exports) {
46055 "use strict"
46056 // Module export pattern from
46057 // https://github.com/umdjs/umd/blob/master/returnExports.js
46058 ;(function (root, factory) {
46059     if (typeof undefined === 'function' && undefined.amd) {
46060         // AMD. Register as an anonymous module.
46061         undefined([], factory);
46062     } else {
46063         // Node. Does not work with strict CommonJS, but
46064         // only CommonJS-like environments that support module.exports,
46065         // like Node.
46066         module.exports = factory();
46067     }
46068 }(commonjsGlobal, function () {
46069         
46070         // Store.js
46071         var store = {},
46072                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
46073                 doc = win.document,
46074                 localStorageName = 'localStorage',
46075                 scriptTag = 'script',
46076                 storage;
46077
46078         store.disabled = false;
46079         store.version = '1.3.20';
46080         store.set = function(key, value) {};
46081         store.get = function(key, defaultVal) {};
46082         store.has = function(key) { return store.get(key) !== undefined };
46083         store.remove = function(key) {};
46084         store.clear = function() {};
46085         store.transact = function(key, defaultVal, transactionFn) {
46086                 if (transactionFn == null) {
46087                         transactionFn = defaultVal;
46088                         defaultVal = null;
46089                 }
46090                 if (defaultVal == null) {
46091                         defaultVal = {};
46092                 }
46093                 var val = store.get(key, defaultVal);
46094                 transactionFn(val);
46095                 store.set(key, val);
46096         };
46097         store.getAll = function() {};
46098         store.forEach = function() {};
46099
46100         store.serialize = function(value) {
46101                 return JSON.stringify(value)
46102         };
46103         store.deserialize = function(value) {
46104                 if (typeof value != 'string') { return undefined }
46105                 try { return JSON.parse(value) }
46106                 catch(e) { return value || undefined }
46107         };
46108
46109         // Functions to encapsulate questionable FireFox 3.6.13 behavior
46110         // when about.config::dom.storage.enabled === false
46111         // See https://github.com/marcuswestin/store.js/issues#issue/13
46112         function isLocalStorageNameSupported() {
46113                 try { return (localStorageName in win && win[localStorageName]) }
46114                 catch(err) { return false }
46115         }
46116
46117         if (isLocalStorageNameSupported()) {
46118                 storage = win[localStorageName];
46119                 store.set = function(key, val) {
46120                         if (val === undefined) { return store.remove(key) }
46121                         storage.setItem(key, store.serialize(val));
46122                         return val
46123                 };
46124                 store.get = function(key, defaultVal) {
46125                         var val = store.deserialize(storage.getItem(key));
46126                         return (val === undefined ? defaultVal : val)
46127                 };
46128                 store.remove = function(key) { storage.removeItem(key); };
46129                 store.clear = function() { storage.clear(); };
46130                 store.getAll = function() {
46131                         var ret = {};
46132                         store.forEach(function(key, val) {
46133                                 ret[key] = val;
46134                         });
46135                         return ret
46136                 };
46137                 store.forEach = function(callback) {
46138                         for (var i=0; i<storage.length; i++) {
46139                                 var key = storage.key(i);
46140                                 callback(key, store.get(key));
46141                         }
46142                 };
46143         } else if (doc && doc.documentElement.addBehavior) {
46144                 var storageOwner,
46145                         storageContainer;
46146                 // Since #userData storage applies only to specific paths, we need to
46147                 // somehow link our data to a specific path.  We choose /favicon.ico
46148                 // as a pretty safe option, since all browsers already make a request to
46149                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
46150                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
46151                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
46152                 // since the iframe access rules appear to allow direct access and
46153                 // manipulation of the document element, even for a 404 page.  This
46154                 // document can be used instead of the current document (which would
46155                 // have been limited to the current path) to perform #userData storage.
46156                 try {
46157                         storageContainer = new ActiveXObject('htmlfile');
46158                         storageContainer.open();
46159                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
46160                         storageContainer.close();
46161                         storageOwner = storageContainer.w.frames[0].document;
46162                         storage = storageOwner.createElement('div');
46163                 } catch(e) {
46164                         // somehow ActiveXObject instantiation failed (perhaps some special
46165                         // security settings or otherwse), fall back to per-path storage
46166                         storage = doc.createElement('div');
46167                         storageOwner = doc.body;
46168                 }
46169                 var withIEStorage = function(storeFunction) {
46170                         return function() {
46171                                 var args = Array.prototype.slice.call(arguments, 0);
46172                                 args.unshift(storage);
46173                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
46174                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
46175                                 storageOwner.appendChild(storage);
46176                                 storage.addBehavior('#default#userData');
46177                                 storage.load(localStorageName);
46178                                 var result = storeFunction.apply(store, args);
46179                                 storageOwner.removeChild(storage);
46180                                 return result
46181                         }
46182                 };
46183
46184                 // In IE7, keys cannot start with a digit or contain certain chars.
46185                 // See https://github.com/marcuswestin/store.js/issues/40
46186                 // See https://github.com/marcuswestin/store.js/issues/83
46187                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
46188                 var ieKeyFix = function(key) {
46189                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
46190                 };
46191                 store.set = withIEStorage(function(storage, key, val) {
46192                         key = ieKeyFix(key);
46193                         if (val === undefined) { return store.remove(key) }
46194                         storage.setAttribute(key, store.serialize(val));
46195                         storage.save(localStorageName);
46196                         return val
46197                 });
46198                 store.get = withIEStorage(function(storage, key, defaultVal) {
46199                         key = ieKeyFix(key);
46200                         var val = store.deserialize(storage.getAttribute(key));
46201                         return (val === undefined ? defaultVal : val)
46202                 });
46203                 store.remove = withIEStorage(function(storage, key) {
46204                         key = ieKeyFix(key);
46205                         storage.removeAttribute(key);
46206                         storage.save(localStorageName);
46207                 });
46208                 store.clear = withIEStorage(function(storage) {
46209                         var attributes = storage.XMLDocument.documentElement.attributes;
46210                         storage.load(localStorageName);
46211                         for (var i=attributes.length-1; i>=0; i--) {
46212                                 storage.removeAttribute(attributes[i].name);
46213                         }
46214                         storage.save(localStorageName);
46215                 });
46216                 store.getAll = function(storage) {
46217                         var ret = {};
46218                         store.forEach(function(key, val) {
46219                                 ret[key] = val;
46220                         });
46221                         return ret
46222                 };
46223                 store.forEach = withIEStorage(function(storage, callback) {
46224                         var attributes = storage.XMLDocument.documentElement.attributes;
46225                         for (var i=0, attr; attr=attributes[i]; ++i) {
46226                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
46227                         }
46228                 });
46229         }
46230
46231         try {
46232                 var testKey = '__storejs__';
46233                 store.set(testKey, testKey);
46234                 if (store.get(testKey) != testKey) { store.disabled = true; }
46235                 store.remove(testKey);
46236         } catch(e) {
46237                 store.disabled = true;
46238         }
46239         store.enabled = !store.disabled;
46240         
46241         return store
46242 }));
46243 });
46244
46245 var ohauth = index$13;
46246 var xtend = immutable;
46247 var store = store$1;
46248
46249 // # osm-auth
46250 //
46251 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
46252 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
46253 // does not support custom headers, which this uses everywhere.
46254 var index$12 = function(o) {
46255
46256     var oauth = {};
46257
46258     // authenticated users will also have a request token secret, but it's
46259     // not used in transactions with the server
46260     oauth.authenticated = function() {
46261         return !!(token('oauth_token') && token('oauth_token_secret'));
46262     };
46263
46264     oauth.logout = function() {
46265         token('oauth_token', '');
46266         token('oauth_token_secret', '');
46267         token('oauth_request_token_secret', '');
46268         return oauth;
46269     };
46270
46271     // TODO: detect lack of click event
46272     oauth.authenticate = function(callback) {
46273         if (oauth.authenticated()) return callback();
46274
46275         oauth.logout();
46276
46277         // ## Getting a request token
46278         var params = timenonce(getAuth(o)),
46279             url = o.url + '/oauth/request_token';
46280
46281         params.oauth_signature = ohauth.signature(
46282             o.oauth_secret, '',
46283             ohauth.baseString('POST', url, params));
46284
46285         if (!o.singlepage) {
46286             // Create a 600x550 popup window in the center of the screen
46287             var w = 600, h = 550,
46288                 settings = [
46289                     ['width', w], ['height', h],
46290                     ['left', screen.width / 2 - w / 2],
46291                     ['top', screen.height / 2 - h / 2]].map(function(x) {
46292                         return x.join('=');
46293                     }).join(','),
46294                 popup = window.open('about:blank', 'oauth_window', settings);
46295         }
46296
46297         // Request a request token. When this is complete, the popup
46298         // window is redirected to OSM's authorization page.
46299         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
46300         o.loading();
46301
46302         function reqTokenDone(err, xhr) {
46303             o.done();
46304             if (err) return callback(err);
46305             var resp = ohauth.stringQs(xhr.response);
46306             token('oauth_request_token_secret', resp.oauth_token_secret);
46307             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
46308                 oauth_token: resp.oauth_token,
46309                 oauth_callback: location.href.replace('index.html', '')
46310                     .replace(/#.*/, '').replace(location.search, '') + o.landing
46311             });
46312
46313             if (o.singlepage) {
46314                 location.href = authorize_url;
46315             } else {
46316                 popup.location = authorize_url;
46317             }
46318         }
46319
46320         // Called by a function in a landing page, in the popup window. The
46321         // window closes itself.
46322         window.authComplete = function(token) {
46323             var oauth_token = ohauth.stringQs(token.split('?')[1]);
46324             get_access_token(oauth_token.oauth_token);
46325             delete window.authComplete;
46326         };
46327
46328         // ## Getting an request token
46329         //
46330         // At this point we have an `oauth_token`, brought in from a function
46331         // call on a landing page popup.
46332         function get_access_token(oauth_token) {
46333             var url = o.url + '/oauth/access_token',
46334                 params = timenonce(getAuth(o)),
46335                 request_token_secret = token('oauth_request_token_secret');
46336             params.oauth_token = oauth_token;
46337             params.oauth_signature = ohauth.signature(
46338                 o.oauth_secret,
46339                 request_token_secret,
46340                 ohauth.baseString('POST', url, params));
46341
46342             // ## Getting an access token
46343             //
46344             // The final token required for authentication. At this point
46345             // we have a `request token secret`
46346             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46347             o.loading();
46348         }
46349
46350         function accessTokenDone(err, xhr) {
46351             o.done();
46352             if (err) return callback(err);
46353             var access_token = ohauth.stringQs(xhr.response);
46354             token('oauth_token', access_token.oauth_token);
46355             token('oauth_token_secret', access_token.oauth_token_secret);
46356             callback(null, oauth);
46357         }
46358     };
46359
46360     oauth.bootstrapToken = function(oauth_token, callback) {
46361         // ## Getting an request token
46362         // At this point we have an `oauth_token`, brought in from a function
46363         // call on a landing page popup.
46364         function get_access_token(oauth_token) {
46365             var url = o.url + '/oauth/access_token',
46366                 params = timenonce(getAuth(o)),
46367                 request_token_secret = token('oauth_request_token_secret');
46368             params.oauth_token = oauth_token;
46369             params.oauth_signature = ohauth.signature(
46370                 o.oauth_secret,
46371                 request_token_secret,
46372                 ohauth.baseString('POST', url, params));
46373
46374             // ## Getting an access token
46375             // The final token required for authentication. At this point
46376             // we have a `request token secret`
46377             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
46378             o.loading();
46379         }
46380
46381         function accessTokenDone(err, xhr) {
46382             o.done();
46383             if (err) return callback(err);
46384             var access_token = ohauth.stringQs(xhr.response);
46385             token('oauth_token', access_token.oauth_token);
46386             token('oauth_token_secret', access_token.oauth_token_secret);
46387             callback(null, oauth);
46388         }
46389
46390         get_access_token(oauth_token);
46391     };
46392
46393     // # xhr
46394     //
46395     // A single XMLHttpRequest wrapper that does authenticated calls if the
46396     // user has logged in.
46397     oauth.xhr = function(options, callback) {
46398         if (!oauth.authenticated()) {
46399             if (o.auto) {
46400                 return oauth.authenticate(run);
46401             } else {
46402                 callback('not authenticated', null);
46403                 return;
46404             }
46405         } else {
46406             return run();
46407         }
46408
46409         function run() {
46410             var params = timenonce(getAuth(o)),
46411                 oauth_token_secret = token('oauth_token_secret'),
46412                 url = (options.prefix !== false) ? o.url + options.path : options.path,
46413                 url_parts = url.replace(/#.*$/, '').split('?', 2),
46414                 base_url = url_parts[0],
46415                 query = (url_parts.length === 2) ? url_parts[1] : '';
46416
46417             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
46418             if ((!options.options || !options.options.header ||
46419                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
46420                 options.content) {
46421                 params = xtend(params, ohauth.stringQs(options.content));
46422             }
46423
46424             params.oauth_token = token('oauth_token');
46425             params.oauth_signature = ohauth.signature(
46426                 o.oauth_secret,
46427                 oauth_token_secret,
46428                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
46429             );
46430
46431             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
46432         }
46433
46434         function done(err, xhr) {
46435             if (err) return callback(err);
46436             else if (xhr.responseXML) return callback(err, xhr.responseXML);
46437             else return callback(err, xhr.response);
46438         }
46439     };
46440
46441     // pre-authorize this object, if we can just get a token and token_secret
46442     // from the start
46443     oauth.preauth = function(c) {
46444         if (!c) return;
46445         if (c.oauth_token) token('oauth_token', c.oauth_token);
46446         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
46447         return oauth;
46448     };
46449
46450     oauth.options = function(_) {
46451         if (!arguments.length) return o;
46452
46453         o = _;
46454         o.url = o.url || 'http://www.openstreetmap.org';
46455         o.landing = o.landing || 'land.html';
46456         o.singlepage = o.singlepage || false;
46457
46458         // Optional loading and loading-done functions for nice UI feedback.
46459         // by default, no-ops
46460         o.loading = o.loading || function() {};
46461         o.done = o.done || function() {};
46462
46463         return oauth.preauth(o);
46464     };
46465
46466     // 'stamp' an authentication object from `getAuth()`
46467     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
46468     // and timestamp
46469     function timenonce(o) {
46470         o.oauth_timestamp = ohauth.timestamp();
46471         o.oauth_nonce = ohauth.nonce();
46472         return o;
46473     }
46474
46475     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46476     // can be used with multiple APIs and the keys in `localStorage`
46477     // will not clash
46478     var token;
46479
46480     if (store.enabled) {
46481         token = function (x, y) {
46482             if (arguments.length === 1) return store.get(o.url + x);
46483             else if (arguments.length === 2) return store.set(o.url + x, y);
46484         };
46485     } else {
46486         var storage = {};
46487         token = function (x, y) {
46488             if (arguments.length === 1) return storage[o.url + x];
46489             else if (arguments.length === 2) return storage[o.url + x] = y;
46490         };
46491     }
46492
46493     // Get an authentication object. If you just add and remove properties
46494     // from a single object, you'll need to use `delete` to make sure that
46495     // it doesn't contain undesired properties for authentication
46496     function getAuth(o) {
46497         return {
46498             oauth_consumer_key: o.oauth_consumer_key,
46499             oauth_signature_method: 'HMAC-SHA1'
46500         };
46501     }
46502
46503     // potentially pre-authorize
46504     oauth.options(o);
46505
46506     return oauth;
46507 };
46508
46509 var JXON = new (function () {
46510   var
46511     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46512     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46513
46514   function parseText (sValue) {
46515     if (rIsNull.test(sValue)) { return null; }
46516     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46517     if (isFinite(sValue)) { return parseFloat(sValue); }
46518     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46519     return sValue;
46520   }
46521
46522   function EmptyTree () { }
46523   EmptyTree.prototype.toString = function () { return 'null'; };
46524   EmptyTree.prototype.valueOf = function () { return null; };
46525
46526   function objectify (vValue) {
46527     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46528   }
46529
46530   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46531     var
46532       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46533       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46534
46535     var
46536       sProp, vContent, nLength = 0, sCollectedTxt = '',
46537       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46538
46539     if (bChildren) {
46540       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46541         oNode = oParentNode.childNodes.item(nItem);
46542         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46543         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46544         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46545       }
46546     }
46547
46548     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46549
46550     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46551
46552     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46553       sProp = aCache[nElId].nodeName.toLowerCase();
46554       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46555       if (vResult.hasOwnProperty(sProp)) {
46556         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46557         vResult[sProp].push(vContent);
46558       } else {
46559         vResult[sProp] = vContent;
46560         nLength++;
46561       }
46562     }
46563
46564     if (bAttributes) {
46565       var
46566         nAttrLen = oParentNode.attributes.length,
46567         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46568
46569       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46570         oAttrib = oParentNode.attributes.item(nAttrib);
46571         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46572       }
46573
46574       if (bNesteAttr) {
46575         if (bFreeze) { Object.freeze(oAttrParent); }
46576         vResult[sAttributesProp] = oAttrParent;
46577         nLength -= nAttrLen - 1;
46578       }
46579     }
46580
46581     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46582       vResult[sValueProp] = vBuiltVal;
46583     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46584       vResult = vBuiltVal;
46585     }
46586
46587     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46588
46589     aCache.length = nLevelStart;
46590
46591     return vResult;
46592   }
46593
46594   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46595     var vValue, oChild;
46596
46597     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46598       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46599     } else if (oParentObj.constructor === Date) {
46600       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46601     }
46602
46603     for (var sName in oParentObj) {
46604       vValue = oParentObj[sName];
46605       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46606       if (sName === sValueProp) {
46607         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46608       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46609         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46610       } else if (sName.charAt(0) === sAttrPref) {
46611         oParentEl.setAttribute(sName.slice(1), vValue);
46612       } else if (vValue.constructor === Array) {
46613         for (var nItem = 0; nItem < vValue.length; nItem++) {
46614           oChild = oXMLDoc.createElement(sName);
46615           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46616           oParentEl.appendChild(oChild);
46617         }
46618       } else {
46619         oChild = oXMLDoc.createElement(sName);
46620         if (vValue instanceof Object) {
46621           loadObjTree(oXMLDoc, oChild, vValue);
46622         } else if (vValue !== null && vValue !== true) {
46623           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46624         }
46625         oParentEl.appendChild(oChild);
46626      }
46627    }
46628   }
46629
46630   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46631     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46632     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46633   };
46634
46635   this.unbuild = function (oObjTree) {    
46636     var oNewDoc = document.implementation.createDocument('', '', null);
46637     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46638     return oNewDoc;
46639   };
46640
46641   this.stringify = function (oObjTree) {
46642     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46643   };
46644 })();
46645
46646 // var myObject = JXON.build(doc);
46647 // we got our javascript object! try: alert(JSON.stringify(myObject));
46648
46649 // var newDoc = JXON.unbuild(myObject);
46650 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46651
46652 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46653 var useHttps = window.location.protocol === 'https:';
46654 var protocol = useHttps ? 'https:' : 'http:';
46655 var urlroot = protocol + '//www.openstreetmap.org';
46656 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46657 var inflight = {};
46658 var loadedTiles = {};
46659 var tileZoom$1 = 16;
46660 var oauth = index$12({
46661         url: urlroot,
46662         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46663         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46664         loading: authLoading,
46665         done: authDone
46666     });
46667 var rateLimitError;
46668 var userChangesets;
46669 var userDetails;
46670 var off;
46671
46672
46673 function authLoading() {
46674     dispatch$3.call('authLoading');
46675 }
46676
46677
46678 function authDone() {
46679     dispatch$3.call('authDone');
46680 }
46681
46682
46683 function abortRequest$1(i) {
46684     if (i) {
46685         i.abort();
46686     }
46687 }
46688
46689
46690 function getLoc(attrs) {
46691     var lon = attrs.lon && attrs.lon.value,
46692         lat = attrs.lat && attrs.lat.value;
46693     return [parseFloat(lon), parseFloat(lat)];
46694 }
46695
46696
46697 function getNodes(obj) {
46698     var elems = obj.getElementsByTagName('nd'),
46699         nodes = new Array(elems.length);
46700     for (var i = 0, l = elems.length; i < l; i++) {
46701         nodes[i] = 'n' + elems[i].attributes.ref.value;
46702     }
46703     return nodes;
46704 }
46705
46706
46707 function getTags(obj) {
46708     var elems = obj.getElementsByTagName('tag'),
46709         tags = {};
46710     for (var i = 0, l = elems.length; i < l; i++) {
46711         var attrs = elems[i].attributes;
46712         tags[attrs.k.value] = attrs.v.value;
46713     }
46714
46715     return tags;
46716 }
46717
46718
46719 function getMembers(obj) {
46720     var elems = obj.getElementsByTagName('member'),
46721         members = new Array(elems.length);
46722     for (var i = 0, l = elems.length; i < l; i++) {
46723         var attrs = elems[i].attributes;
46724         members[i] = {
46725             id: attrs.type.value[0] + attrs.ref.value,
46726             type: attrs.type.value,
46727             role: attrs.role.value
46728         };
46729     }
46730     return members;
46731 }
46732
46733
46734 function getVisible(attrs) {
46735     return (!attrs.visible || attrs.visible.value !== 'false');
46736 }
46737
46738
46739 var parsers = {
46740     node: function nodeData(obj) {
46741         var attrs = obj.attributes;
46742         return new osmNode({
46743             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46744             loc: getLoc(attrs),
46745             version: attrs.version.value,
46746             user: attrs.user && attrs.user.value,
46747             tags: getTags(obj),
46748             visible: getVisible(attrs)
46749         });
46750     },
46751
46752     way: function wayData(obj) {
46753         var attrs = obj.attributes;
46754         return new osmWay({
46755             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46756             version: attrs.version.value,
46757             user: attrs.user && attrs.user.value,
46758             tags: getTags(obj),
46759             nodes: getNodes(obj),
46760             visible: getVisible(attrs)
46761         });
46762     },
46763
46764     relation: function relationData(obj) {
46765         var attrs = obj.attributes;
46766         return new osmRelation({
46767             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46768             version: attrs.version.value,
46769             user: attrs.user && attrs.user.value,
46770             tags: getTags(obj),
46771             members: getMembers(obj),
46772             visible: getVisible(attrs)
46773         });
46774     }
46775 };
46776
46777
46778 function parse(xml$$1) {
46779     if (!xml$$1 || !xml$$1.childNodes) return;
46780
46781     var root = xml$$1.childNodes[0],
46782         children = root.childNodes,
46783         entities = [];
46784
46785     for (var i = 0, l = children.length; i < l; i++) {
46786         var child = children[i],
46787             parser = parsers[child.nodeName];
46788         if (parser) {
46789             entities.push(parser(child));
46790         }
46791     }
46792
46793     return entities;
46794 }
46795
46796
46797 var serviceOsm = {
46798
46799     init: function() {
46800         utilRebind(this, dispatch$3, 'on');
46801     },
46802
46803
46804     reset: function() {
46805         userChangesets = undefined;
46806         userDetails = undefined;
46807         rateLimitError = undefined;
46808         lodash.forEach(inflight, abortRequest$1);
46809         loadedTiles = {};
46810         inflight = {};
46811         return this;
46812     },
46813
46814
46815     changesetURL: function(changesetId) {
46816         return urlroot + '/changeset/' + changesetId;
46817     },
46818
46819
46820     changesetsURL: function(center, zoom$$1) {
46821         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46822         return urlroot + '/history#map=' +
46823             Math.floor(zoom$$1) + '/' +
46824             center[1].toFixed(precision) + '/' +
46825             center[0].toFixed(precision);
46826     },
46827
46828
46829     entityURL: function(entity) {
46830         return urlroot + '/' + entity.type + '/' + entity.osmId();
46831     },
46832
46833
46834     userURL: function(username) {
46835         return urlroot + '/user/' + username;
46836     },
46837
46838
46839     loadFromAPI: function(path$$1, callback) {
46840         var that = this;
46841
46842         function done(err, xml$$1) {
46843             var isAuthenticated = that.authenticated();
46844
46845             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46846             // Logout and retry the request..
46847             if (isAuthenticated && err &&
46848                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46849                 that.logout();
46850                 that.loadFromAPI(path$$1, callback);
46851
46852             // else, no retry..
46853             } else {
46854                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46855                 // Set the rateLimitError flag and trigger a warning..
46856                 if (!isAuthenticated && !rateLimitError && err &&
46857                         (err.status === 509 || err.status === 429)) {
46858                     rateLimitError = err;
46859                     dispatch$3.call('change');
46860                 }
46861
46862                 if (callback) {
46863                     callback(err, parse(xml$$1));
46864                 }
46865             }
46866         }
46867
46868         if (this.authenticated()) {
46869             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46870         } else {
46871             var url = urlroot + path$$1;
46872             return xml(url).get(done);
46873         }
46874     },
46875
46876
46877     loadEntity: function(id, callback) {
46878         var type = osmEntity$$1.id.type(id),
46879             osmID = osmEntity$$1.id.toOSM(id);
46880
46881         this.loadFromAPI(
46882             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46883             function(err, entities) {
46884                 if (callback) callback(err, { data: entities });
46885             }
46886         );
46887     },
46888
46889
46890     loadEntityVersion: function(id, version$$1, callback) {
46891         var type = osmEntity$$1.id.type(id),
46892             osmID = osmEntity$$1.id.toOSM(id);
46893
46894         this.loadFromAPI(
46895             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46896             function(err, entities) {
46897                 if (callback) callback(err, { data: entities });
46898             }
46899         );
46900     },
46901
46902
46903     loadMultiple: function(ids, callback) {
46904         var that = this;
46905         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46906             var type = k + 's',
46907                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46908
46909             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46910                 that.loadFromAPI(
46911                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46912                     function(err, entities) {
46913                         if (callback) callback(err, { data: entities });
46914                     }
46915                 );
46916             });
46917         });
46918     },
46919
46920
46921     authenticated: function() {
46922         return oauth.authenticated();
46923     },
46924
46925
46926     // Generate Changeset XML. Returns a string.
46927     changesetJXON: function(tags) {
46928         return {
46929             osm: {
46930                 changeset: {
46931                     tag: lodash.map(tags, function(value, key) {
46932                         return { '@k': key, '@v': value };
46933                     }),
46934                     '@version': 0.6,
46935                     '@generator': 'iD'
46936                 }
46937             }
46938         };
46939     },
46940
46941
46942     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46943     // XML. Returns a string.
46944     osmChangeJXON: function(changeset_id, changes) {
46945         function nest$$1(x, order) {
46946             var groups = {};
46947             for (var i = 0; i < x.length; i++) {
46948                 var tagName = Object.keys(x[i])[0];
46949                 if (!groups[tagName]) groups[tagName] = [];
46950                 groups[tagName].push(x[i][tagName]);
46951             }
46952             var ordered = {};
46953             order.forEach(function(o) {
46954                 if (groups[o]) ordered[o] = groups[o];
46955             });
46956             return ordered;
46957         }
46958
46959         function rep(entity) {
46960             return entity.asJXON(changeset_id);
46961         }
46962
46963         return {
46964             osmChange: {
46965                 '@version': 0.6,
46966                 '@generator': 'iD',
46967                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
46968                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
46969                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
46970             }
46971         };
46972     },
46973
46974
46975     changesetTags: function(version$$1, comment, imageryUsed) {
46976         var detected = utilDetect(),
46977             tags = {
46978                 created_by: ('iD ' + version$$1).substr(0, 255),
46979                 imagery_used: imageryUsed.join(';').substr(0, 255),
46980                 host: detected.host.substr(0, 255),
46981                 locale: detected.locale.substr(0, 255)
46982             };
46983
46984         if (comment) {
46985             tags.comment = comment.substr(0, 255);
46986         }
46987
46988         return tags;
46989     },
46990
46991
46992     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
46993         var that = this;
46994         oauth.xhr({
46995                 method: 'PUT',
46996                 path: '/api/0.6/changeset/create',
46997                 options: { header: { 'Content-Type': 'text/xml' } },
46998                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
46999             }, function(err, changeset_id) {
47000                 if (err) return callback(err);
47001                 oauth.xhr({
47002                     method: 'POST',
47003                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
47004                     options: { header: { 'Content-Type': 'text/xml' } },
47005                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
47006                 }, function(err) {
47007                     if (err) return callback(err);
47008                     // POST was successful, safe to call the callback.
47009                     // Still attempt to close changeset, but ignore response because #2667
47010                     // Add delay to allow for postgres replication #1646 #2678
47011                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
47012                     oauth.xhr({
47013                         method: 'PUT',
47014                         path: '/api/0.6/changeset/' + changeset_id + '/close',
47015                         options: { header: { 'Content-Type': 'text/xml' } }
47016                     }, function() { return true; });
47017                 });
47018             });
47019     },
47020
47021
47022     userDetails: function(callback) {
47023         if (userDetails) {
47024             callback(undefined, userDetails);
47025             return;
47026         }
47027
47028         function done(err, user_details) {
47029             if (err) return callback(err);
47030
47031             var u = user_details.getElementsByTagName('user')[0],
47032                 img = u.getElementsByTagName('img'),
47033                 image_url = '';
47034
47035             if (img && img[0] && img[0].getAttribute('href')) {
47036                 image_url = img[0].getAttribute('href');
47037             }
47038
47039             userDetails = {
47040                 display_name: u.attributes.display_name.value,
47041                 image_url: image_url,
47042                 id: u.attributes.id.value
47043             };
47044
47045             callback(undefined, userDetails);
47046         }
47047
47048         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
47049     },
47050
47051
47052     userChangesets: function(callback) {
47053         if (userChangesets) {
47054             callback(undefined, userChangesets);
47055             return;
47056         }
47057
47058         this.userDetails(function(err, user) {
47059             if (err) {
47060                 callback(err);
47061                 return;
47062             }
47063
47064             function done(err, changesets) {
47065                 if (err) {
47066                     callback(err);
47067                 } else {
47068                     userChangesets = Array.prototype.map.call(
47069                         changesets.getElementsByTagName('changeset'),
47070                         function (changeset) {
47071                             return { tags: getTags(changeset) };
47072                         }
47073                     );
47074                     callback(undefined, userChangesets);
47075                 }
47076             }
47077
47078             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
47079         });
47080     },
47081
47082
47083     status: function(callback) {
47084         function done(xml$$1) {
47085             // update blacklists
47086             var elements = xml$$1.getElementsByTagName('blacklist'),
47087                 regexes = [];
47088             for (var i = 0; i < elements.length; i++) {
47089                 var regex = elements[i].getAttribute('regex');  // needs unencode?
47090                 if (regex) {
47091                     regexes.push(regex);
47092                 }
47093             }
47094             if (regexes.length) {
47095                 blacklists = regexes;
47096             }
47097
47098
47099             if (rateLimitError) {
47100                 callback(rateLimitError, 'rateLimited');
47101             } else {
47102                 var apiStatus = xml$$1.getElementsByTagName('status'),
47103                     val = apiStatus[0].getAttribute('api');
47104
47105                 callback(undefined, val);
47106             }
47107         }
47108
47109         xml(urlroot + '/api/capabilities').get()
47110             .on('load', done)
47111             .on('error', callback);
47112     },
47113
47114
47115     imageryBlacklists: function() {
47116         return blacklists;
47117     },
47118
47119
47120     tileZoom: function(_) {
47121         if (!arguments.length) return tileZoom$1;
47122         tileZoom$1 = _;
47123         return this;
47124     },
47125
47126
47127     loadTiles: function(projection, dimensions, callback) {
47128         if (off) return;
47129
47130         var that = this,
47131             s = projection.scale() * 2 * Math.PI,
47132             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
47133             ts = 256 * Math.pow(2, z - tileZoom$1),
47134             origin = [
47135                 s / 2 - projection.translate()[0],
47136                 s / 2 - projection.translate()[1]
47137             ];
47138
47139         var tiles = d3geoTile()
47140             .scaleExtent([tileZoom$1, tileZoom$1])
47141             .scale(s)
47142             .size(dimensions)
47143             .translate(projection.translate())()
47144             .map(function(tile) {
47145                 var x = tile[0] * ts - origin[0],
47146                     y = tile[1] * ts - origin[1];
47147
47148                 return {
47149                     id: tile.toString(),
47150                     extent: geoExtent$$1(
47151                         projection.invert([x, y + ts]),
47152                         projection.invert([x + ts, y]))
47153                 };
47154             });
47155
47156         lodash.filter(inflight, function(v, i) {
47157             var wanted = lodash.find(tiles, function(tile) {
47158                 return i === tile.id;
47159             });
47160             if (!wanted) delete inflight[i];
47161             return !wanted;
47162         }).map(abortRequest$1);
47163
47164         tiles.forEach(function(tile) {
47165             var id = tile.id;
47166
47167             if (loadedTiles[id] || inflight[id]) return;
47168
47169             if (lodash.isEmpty(inflight)) {
47170                 dispatch$3.call('loading');
47171             }
47172
47173             inflight[id] = that.loadFromAPI(
47174                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
47175                 function(err, parsed) {
47176                     delete inflight[id];
47177                     if (!err) {
47178                         loadedTiles[id] = true;
47179                     }
47180
47181                     if (callback) {
47182                         callback(err, lodash.extend({ data: parsed }, tile));
47183                     }
47184
47185                     if (lodash.isEmpty(inflight)) {
47186                         dispatch$3.call('loaded');
47187                     }
47188                 }
47189             );
47190         });
47191     },
47192
47193
47194     switch: function(options) {
47195         urlroot = options.urlroot;
47196
47197         oauth.options(lodash.extend({
47198             url: urlroot,
47199             loading: authLoading,
47200             done: authDone
47201         }, options));
47202
47203         dispatch$3.call('change');
47204         this.reset();
47205         this.userChangesets(function() {});  // eagerly load user details/changesets
47206         return this;
47207     },
47208
47209
47210     toggle: function(_) {
47211         off = !_;
47212         return this;
47213     },
47214
47215
47216     loadedTiles: function(_) {
47217         if (!arguments.length) return loadedTiles;
47218         loadedTiles = _;
47219         return this;
47220     },
47221
47222
47223     logout: function() {
47224         userChangesets = undefined;
47225         userDetails = undefined;
47226         oauth.logout();
47227         dispatch$3.call('change');
47228         return this;
47229     },
47230
47231
47232     authenticate: function(callback) {
47233         var that = this;
47234         userChangesets = undefined;
47235         userDetails = undefined;
47236
47237         function done(err, res) {
47238             rateLimitError = undefined;
47239             dispatch$3.call('change');
47240             if (callback) callback(err, res);
47241             that.userChangesets(function() {});  // eagerly load user details/changesets
47242         }
47243
47244         return oauth.authenticate(done);
47245     }
47246 };
47247
47248 var endpoint = 'https://taginfo.openstreetmap.org/api/4/';
47249 var taginfoCache = {};
47250 var tag_sorts = {
47251         point: 'count_nodes',
47252         vertex: 'count_nodes',
47253         area: 'count_ways',
47254         line: 'count_ways'
47255     };
47256 var tag_sort_members = {
47257         point: 'count_node_members',
47258         vertex: 'count_node_members',
47259         area: 'count_way_members',
47260         line: 'count_way_members',
47261         relation: 'count_relation_members'
47262     };
47263 var tag_filters = {
47264         point: 'nodes',
47265         vertex: 'nodes',
47266         area: 'ways',
47267         line: 'ways'
47268     };
47269 var tag_members_fractions = {
47270         point: 'count_node_members_fraction',
47271         vertex: 'count_node_members_fraction',
47272         area: 'count_way_members_fraction',
47273         line: 'count_way_members_fraction',
47274         relation: 'count_relation_members_fraction'
47275     };
47276
47277
47278 function sets(parameters, n, o) {
47279     if (parameters.geometry && o[parameters.geometry]) {
47280         parameters[n] = o[parameters.geometry];
47281     }
47282     return parameters;
47283 }
47284
47285
47286 function setFilter(parameters) {
47287     return sets(parameters, 'filter', tag_filters);
47288 }
47289
47290
47291 function setSort(parameters) {
47292     return sets(parameters, 'sortname', tag_sorts);
47293 }
47294
47295
47296 function setSortMembers(parameters) {
47297     return sets(parameters, 'sortname', tag_sort_members);
47298 }
47299
47300
47301 function clean(parameters) {
47302     return lodash.omit(parameters, 'geometry', 'debounce');
47303 }
47304
47305
47306 function filterKeys(type) {
47307     var count_type = type ? 'count_' + type : 'count_all';
47308     return function(d) {
47309         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
47310     };
47311 }
47312
47313
47314 function filterMultikeys(prefix) {
47315     return function(d) {
47316         // d.key begins with prefix, and d.key contains no additional ':'s
47317         var re = new RegExp('^' + prefix + '(.*)$');
47318         var matches = d.key.match(re) || [];
47319         return (matches.length === 2 && matches[1].indexOf(':') === -1);
47320     };
47321 }
47322
47323
47324 function filterValues(allowUpperCase) {
47325     return function(d) {
47326         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
47327         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
47328         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
47329     };
47330 }
47331
47332
47333 function filterRoles(geometry) {
47334     return function(d) {
47335         if (d.role === '') return false; // exclude empty role
47336         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
47337         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
47338     };
47339 }
47340
47341
47342 function valKey(d) {
47343     return {
47344         value: d.key,
47345         title: d.key
47346     };
47347 }
47348
47349
47350 function valKeyDescription(d) {
47351     return {
47352         value: d.value,
47353         title: d.description || d.value
47354     };
47355 }
47356
47357
47358 function roleKey(d) {
47359     return {
47360         value: d.role,
47361         title: d.role
47362     };
47363 }
47364
47365
47366 // sort keys with ':' lower than keys without ':'
47367 function sortKeys(a, b) {
47368     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
47369         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
47370         : 0;
47371 }
47372
47373
47374 var debounced = lodash.debounce(json, 100, true);
47375
47376
47377 function request$1(url, debounce, callback) {
47378     if (taginfoCache[url]) {
47379         callback(null, taginfoCache[url]);
47380     } else if (debounce) {
47381         debounced(url, done);
47382     } else {
47383         json(url, done);
47384     }
47385
47386     function done(err, data) {
47387         if (!err) {
47388             taginfoCache[url] = data;
47389         }
47390         callback(err, data);
47391     }
47392 }
47393
47394
47395 var serviceTaginfo = {
47396
47397     init: function() { taginfoCache = {}; },
47398     reset: function() { taginfoCache = {}; },
47399
47400
47401     keys: function(parameters, callback) {
47402         var debounce = parameters.debounce;
47403         parameters = clean(setSort(parameters));
47404         request$1(endpoint + 'keys/all?' +
47405             utilQsString(lodash.extend({
47406                 rp: 10,
47407                 sortname: 'count_all',
47408                 sortorder: 'desc',
47409                 page: 1
47410             }, parameters)), debounce, function(err, d) {
47411                 if (err) {
47412                     callback(err);
47413                 } else {
47414                     var f = filterKeys(parameters.filter);
47415                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
47416                 }
47417             }
47418         );
47419     },
47420
47421
47422     multikeys: function(parameters, callback) {
47423         var debounce = parameters.debounce;
47424         parameters = clean(setSort(parameters));
47425         var prefix = parameters.query;
47426         request$1(endpoint + 'keys/all?' +
47427             utilQsString(lodash.extend({
47428                 rp: 25,
47429                 sortname: 'count_all',
47430                 sortorder: 'desc',
47431                 page: 1
47432             }, parameters)), debounce, function(err, d) {
47433                 if (err) {
47434                     callback(err);
47435                 } else {
47436                     var f = filterMultikeys(prefix);
47437                     callback(null, d.data.filter(f).map(valKey));
47438                 }
47439             }
47440         );
47441     },
47442
47443
47444     values: function(parameters, callback) {
47445         var debounce = parameters.debounce;
47446         parameters = clean(setSort(setFilter(parameters)));
47447         request$1(endpoint + 'key/values?' +
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                     // In most cases we prefer taginfo value results with lowercase letters.
47458                     // A few OSM keys expect values to contain uppercase values (see #3377).
47459                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
47460                     // but these are the fields where taginfo value lookup is most useful.
47461                     var re = /network|taxon|genus|species/;
47462                     var allowUpperCase = (parameters.key.match(re) !== null);
47463                     var f = filterValues(allowUpperCase);
47464                     callback(null, d.data.filter(f).map(valKeyDescription));
47465                 }
47466             }
47467         );
47468     },
47469
47470
47471     roles: function(parameters, callback) {
47472         var debounce = parameters.debounce;
47473         var geometry = parameters.geometry;
47474         parameters = clean(setSortMembers(parameters));
47475         request$1(endpoint + 'relation/roles?' +
47476             utilQsString(lodash.extend({
47477                 rp: 25,
47478                 sortname: 'count_all_members',
47479                 sortorder: 'desc',
47480                 page: 1
47481             }, parameters)), debounce, function(err, d) {
47482                 if (err) {
47483                     callback(err);
47484                 } else {
47485                     var f = filterRoles(geometry);
47486                     callback(null, d.data.filter(f).map(roleKey));
47487                 }
47488             }
47489         );
47490     },
47491
47492
47493     docs: function(parameters, callback) {
47494         var debounce = parameters.debounce;
47495         parameters = clean(setSort(parameters));
47496
47497         var path$$1 = 'key/wiki_pages?';
47498         if (parameters.value) path$$1 = 'tag/wiki_pages?';
47499         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
47500
47501         request$1(endpoint + path$$1 + utilQsString(parameters), debounce, function(err, d) {
47502             if (err) {
47503                 callback(err);
47504             } else {
47505                 callback(null, d.data);
47506             }
47507         });
47508     },
47509
47510
47511     endpoint: function(_) {
47512         if (!arguments.length) return endpoint;
47513         endpoint = _;
47514         return this;
47515     }
47516
47517 };
47518
47519 var jsonpCache = {};
47520 window.jsonpCache = jsonpCache;
47521
47522 function jsonpRequest(url, callback) {
47523
47524   if (window.JSONP_FIX) {
47525     if (window.JSONP_DELAY === 0) {
47526       callback(window.JSONP_FIX);
47527     } else {
47528       setTimeout(function() {
47529         callback(window.JSONP_FIX);
47530       }, window.JSONP_DELAY || 0);
47531     }
47532     return;
47533   }
47534
47535   function rand() {
47536     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47537       c = '', i = -1;
47538     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47539     return c;
47540   }
47541
47542   function create(url) {
47543     var e = url.match(/callback=(\w+)/),
47544       c = e ? e[1] : rand();
47545     jsonpCache[c] = function(data) {
47546       callback(data);
47547       delete jsonpCache[c];
47548       script.remove();
47549     };
47550     return 'jsonpCache.' + c;
47551   }
47552
47553   var cb = create(url),
47554     script = select('head')
47555     .append('script')
47556     .attr('type', 'text/javascript')
47557     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47558 }
47559
47560 var endpoint$1 = 'https://www.wikidata.org/w/api.php?';
47561
47562 var serviceWikidata = {
47563
47564     init: function() {},
47565     reset: function() {},
47566
47567
47568     // Given a Wikipedia language and article title, return an array of
47569     // corresponding Wikidata entities.
47570     itemsByTitle: function(lang, title, callback) {
47571         if (!title) {
47572             callback('', {});
47573             return;
47574         }
47575
47576         lang = lang || 'en';
47577         jsonpRequest(endpoint$1 + utilQsString({
47578             action: 'wbgetentities',
47579             format: 'json',
47580             sites: lang.replace(/-/g, '_') + 'wiki',
47581             titles: title,
47582             languages: 'en', // shrink response by filtering to one language
47583             callback: '{callback}'
47584         }), function(data) {
47585             if (!data || data.error) {
47586                 callback('', {});
47587             } else {
47588                 callback(title, data.entities || {});
47589             }
47590         });
47591     }
47592
47593 };
47594
47595 var endpoint$2 = 'https://en.wikipedia.org/w/api.php?';
47596
47597 var serviceWikipedia = {
47598
47599     init: function() {},
47600     reset: function() {},
47601
47602
47603     search: function(lang, query, callback) {
47604         if (!query) {
47605             callback('', []);
47606             return;
47607         }
47608
47609         lang = lang || 'en';
47610         jsonpRequest(endpoint$2.replace('en', lang) +
47611             utilQsString({
47612                 action: 'query',
47613                 list: 'search',
47614                 srlimit: '10',
47615                 srinfo: 'suggestion',
47616                 format: 'json',
47617                 callback: '{callback}',
47618                 srsearch: query
47619             }), function(data) {
47620                 if (!data || !data.query || !data.query.search || data.error) {
47621                     callback('', []);
47622                 } else {
47623                     var results = data.query.search.map(function(d) { return d.title; });
47624                     callback(query, results);
47625                 }
47626             }
47627         );
47628     },
47629
47630
47631     suggestions: function(lang, query, callback) {
47632         if (!query) {
47633             callback('', []);
47634             return;
47635         }
47636
47637         lang = lang || 'en';
47638         jsonpRequest(endpoint$2.replace('en', lang) +
47639             utilQsString({
47640                 action: 'opensearch',
47641                 namespace: 0,
47642                 suggest: '',
47643                 format: 'json',
47644                 callback: '{callback}',
47645                 search: query
47646             }), function(data) {
47647                 if (!data || data.error) {
47648                     callback('', []);
47649                 } else {
47650                     callback(data[0], data[1] || []);
47651                 }
47652             }
47653         );
47654     },
47655
47656
47657     translations: function(lang, title, callback) {
47658         if (!title) {
47659             callback({});
47660             return;
47661         }
47662
47663         jsonpRequest(endpoint$2.replace('en', lang) +
47664             utilQsString({
47665                 action: 'query',
47666                 prop: 'langlinks',
47667                 format: 'json',
47668                 callback: '{callback}',
47669                 lllimit: 500,
47670                 titles: title
47671             }), function(data) {
47672                 if (!data || !data.query || !data.query.pages || data.error) {
47673                     callback({});
47674                 } else {
47675                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47676                         translations = {};
47677                     if (list && list.langlinks) {
47678                         list.langlinks.forEach(function(d) {
47679                             translations[d.lang] = d['*'];
47680                         });
47681                     }
47682                     callback(translations);
47683                 }
47684             }
47685         );
47686     }
47687
47688 };
47689
47690 var services = {
47691     mapillary: serviceMapillary,
47692     geocoder: serviceNominatim,
47693     osm: serviceOsm,
47694     taginfo: serviceTaginfo,
47695     wikidata: serviceWikidata,
47696     wikipedia: serviceWikipedia
47697 };
47698
47699 function svgMapillaryImages(projection, context, dispatch$$1) {
47700     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47701         minZoom = 12,
47702         minViewfieldZoom = 17,
47703         layer = select(null),
47704         _mapillary;
47705
47706
47707     function init() {
47708         if (svgMapillaryImages.initialized) return;  // run once
47709         svgMapillaryImages.enabled = false;
47710         svgMapillaryImages.initialized = true;
47711     }
47712
47713
47714     function getMapillary() {
47715         if (services.mapillary && !_mapillary) {
47716             _mapillary = services.mapillary;
47717             _mapillary.event.on('loadedImages', throttledRedraw);
47718         } else if (!services.mapillary && _mapillary) {
47719             _mapillary = null;
47720         }
47721
47722         return _mapillary;
47723     }
47724
47725
47726     function showLayer() {
47727         var mapillary = getMapillary();
47728         if (!mapillary) return;
47729
47730         mapillary.loadViewer(context);
47731         editOn();
47732
47733         layer
47734             .style('opacity', 0)
47735             .transition()
47736             .duration(500)
47737             .style('opacity', 1)
47738             .on('end', function () { dispatch$$1.call('change'); });
47739     }
47740
47741
47742     function hideLayer() {
47743         var mapillary = getMapillary();
47744         if (mapillary) {
47745             mapillary.hideViewer();
47746         }
47747
47748         throttledRedraw.cancel();
47749
47750         layer
47751             .transition()
47752             .duration(500)
47753             .style('opacity', 0)
47754             .on('end', editOff);
47755     }
47756
47757
47758     function editOn() {
47759         layer.style('display', 'block');
47760     }
47761
47762
47763     function editOff() {
47764         layer.selectAll('.viewfield-group').remove();
47765         layer.style('display', 'none');
47766     }
47767
47768
47769     function click(d) {
47770         var mapillary = getMapillary();
47771         if (!mapillary) return;
47772
47773         context.map().centerEase(d.loc);
47774
47775         mapillary
47776             .selectedImage(d.key, true)
47777             .updateViewer(d.key, context)
47778             .showViewer();
47779     }
47780
47781
47782     function transform(d) {
47783         var t = svgPointTransform(projection)(d);
47784         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47785         return t;
47786     }
47787
47788
47789     function update() {
47790         var mapillary = getMapillary(),
47791             data = (mapillary ? mapillary.images(projection) : []),
47792             imageKey = mapillary ? mapillary.selectedImage() : null;
47793
47794         var markers = layer.selectAll('.viewfield-group')
47795             .data(data, function(d) { return d.key; });
47796
47797         markers.exit()
47798             .remove();
47799
47800         var enter = markers.enter()
47801             .append('g')
47802             .attr('class', 'viewfield-group')
47803             .classed('selected', function(d) { return d.key === imageKey; })
47804             .on('click', click);
47805
47806         markers = markers
47807             .merge(enter)
47808             .attr('transform', transform);
47809
47810
47811        var viewfields = markers.selectAll('.viewfield')
47812             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47813
47814         viewfields.exit()
47815             .remove();
47816
47817         viewfields.enter()
47818             .append('path')
47819             .attr('class', 'viewfield')
47820             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47821             .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');
47822
47823         markers.selectAll('circle')
47824             .data([0])
47825             .enter()
47826             .append('circle')
47827             .attr('dx', '0')
47828             .attr('dy', '0')
47829             .attr('r', '6');
47830     }
47831
47832
47833     function drawImages(selection$$1) {
47834         var enabled = svgMapillaryImages.enabled,
47835             mapillary = getMapillary();
47836
47837         layer = selection$$1.selectAll('.layer-mapillary-images')
47838             .data(mapillary ? [0] : []);
47839
47840         layer.exit()
47841             .remove();
47842
47843         layer = layer.enter()
47844             .append('g')
47845             .attr('class', 'layer-mapillary-images')
47846             .style('display', enabled ? 'block' : 'none')
47847             .merge(layer);
47848
47849         if (enabled) {
47850             if (mapillary && ~~context.map().zoom() >= minZoom) {
47851                 editOn();
47852                 update();
47853                 mapillary.loadImages(projection);
47854             } else {
47855                 editOff();
47856             }
47857         }
47858     }
47859
47860
47861     drawImages.enabled = function(_) {
47862         if (!arguments.length) return svgMapillaryImages.enabled;
47863         svgMapillaryImages.enabled = _;
47864         if (svgMapillaryImages.enabled) {
47865             showLayer();
47866         } else {
47867             hideLayer();
47868         }
47869         dispatch$$1.call('change');
47870         return this;
47871     };
47872
47873
47874     drawImages.supported = function() {
47875         return !!getMapillary();
47876     };
47877
47878
47879     init();
47880     return drawImages;
47881 }
47882
47883 function svgMapillarySigns(projection, context, dispatch$$1) {
47884     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47885         minZoom = 12,
47886         layer = select(null),
47887         _mapillary;
47888
47889
47890     function init() {
47891         if (svgMapillarySigns.initialized) return;  // run once
47892         svgMapillarySigns.enabled = false;
47893         svgMapillarySigns.initialized = true;
47894     }
47895
47896
47897     function getMapillary() {
47898         if (services.mapillary && !_mapillary) {
47899             _mapillary = services.mapillary;
47900             _mapillary.event.on('loadedSigns', throttledRedraw);
47901         } else if (!services.mapillary && _mapillary) {
47902             _mapillary = null;
47903         }
47904         return _mapillary;
47905     }
47906
47907
47908     function showLayer() {
47909         editOn();
47910     }
47911
47912
47913     function hideLayer() {
47914         throttledRedraw.cancel();
47915         editOff();
47916     }
47917
47918
47919     function editOn() {
47920         layer.style('display', 'block');
47921     }
47922
47923
47924     function editOff() {
47925         layer.selectAll('.icon-sign').remove();
47926         layer.style('display', 'none');
47927     }
47928
47929
47930     function click(d) {
47931         var mapillary = getMapillary();
47932         if (!mapillary) return;
47933
47934         context.map().centerEase(d.loc);
47935
47936         mapillary
47937             .selectedImage(d.key, true)
47938             .updateViewer(d.key, context)
47939             .showViewer();
47940     }
47941
47942
47943     function update() {
47944         var mapillary = getMapillary(),
47945             data = (mapillary ? mapillary.signs(projection) : []),
47946             imageKey = mapillary ? mapillary.selectedImage() : null;
47947
47948         var signs = layer.selectAll('.icon-sign')
47949             .data(data, function(d) { return d.key; });
47950
47951         signs.exit()
47952             .remove();
47953
47954         var enter = signs.enter()
47955             .append('foreignObject')
47956             .attr('class', 'icon-sign')
47957             .attr('width', '32px')      // for Firefox
47958             .attr('height', '32px')     // for Firefox
47959             .classed('selected', function(d) { return d.key === imageKey; })
47960             .on('click', click);
47961
47962         enter
47963             .append('xhtml:body')
47964             .attr('class', 'icon-sign-body')
47965             .html(mapillary.signHTML);
47966
47967         signs
47968             .merge(enter)
47969             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
47970             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
47971     }
47972
47973
47974     function drawSigns(selection$$1) {
47975         var enabled = svgMapillarySigns.enabled,
47976             mapillary = getMapillary();
47977
47978         layer = selection$$1.selectAll('.layer-mapillary-signs')
47979             .data(mapillary ? [0] : []);
47980
47981         layer.exit()
47982             .remove();
47983
47984         layer = layer.enter()
47985             .append('g')
47986             .attr('class', 'layer-mapillary-signs')
47987             .style('display', enabled ? 'block' : 'none')
47988             .merge(layer);
47989
47990         if (enabled) {
47991             if (mapillary && ~~context.map().zoom() >= minZoom) {
47992                 editOn();
47993                 update();
47994                 mapillary.loadSigns(context, projection);
47995             } else {
47996                 editOff();
47997             }
47998         }
47999     }
48000
48001
48002     drawSigns.enabled = function(_) {
48003         if (!arguments.length) return svgMapillarySigns.enabled;
48004         svgMapillarySigns.enabled = _;
48005         if (svgMapillarySigns.enabled) {
48006             showLayer();
48007         } else {
48008             hideLayer();
48009         }
48010         dispatch$$1.call('change');
48011         return this;
48012     };
48013
48014
48015     drawSigns.supported = function() {
48016         var mapillary = getMapillary();
48017         return (mapillary && mapillary.signsSupported());
48018     };
48019
48020
48021     init();
48022     return drawSigns;
48023 }
48024
48025 function svgOsm() {
48026     return function drawOsm(selection) {
48027         var layers = selection.selectAll('.layer-osm')
48028             .data(['areas', 'lines', 'hit', 'halo', 'label']);
48029
48030         layers.enter()
48031             .append('g')
48032             .attr('class', function(d) { return 'layer-osm layer-' + d; });
48033     };
48034 }
48035
48036 function svgLayers(projection, context) {
48037     var dispatch$$1 = dispatch('change'),
48038         svg = select(null),
48039         layers = [
48040             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
48041             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
48042             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
48043             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
48044             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
48045         ];
48046
48047
48048     function drawLayers(selection$$1) {
48049         svg = selection$$1.selectAll('.surface')
48050             .data([0]);
48051
48052         svg = svg.enter()
48053             .append('svg')
48054             .attr('class', 'surface')
48055             .merge(svg);
48056
48057         var defs = svg.selectAll('.surface-defs')
48058             .data([0]);
48059
48060         defs.enter()
48061             .append('defs')
48062             .attr('class', 'surface-defs');
48063
48064         var groups = svg.selectAll('.data-layer')
48065             .data(layers);
48066
48067         groups.exit()
48068             .remove();
48069
48070         groups.enter()
48071             .append('g')
48072             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
48073             .merge(groups)
48074             .each(function(d) { select(this).call(d.layer); });
48075     }
48076
48077
48078     drawLayers.all = function() {
48079         return layers;
48080     };
48081
48082
48083     drawLayers.layer = function(id) {
48084         var obj = lodash.find(layers, function(o) {return o.id === id;});
48085         return obj && obj.layer;
48086     };
48087
48088
48089     drawLayers.only = function(what) {
48090         var arr = [].concat(what);
48091         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
48092         return this;
48093     };
48094
48095
48096     drawLayers.remove = function(what) {
48097         var arr = [].concat(what);
48098         arr.forEach(function(id) {
48099             layers = lodash.reject(layers, function(o) {return o.id === id;});
48100         });
48101         dispatch$$1.call('change');
48102         return this;
48103     };
48104
48105
48106     drawLayers.add = function(what) {
48107         var arr = [].concat(what);
48108         arr.forEach(function(obj) {
48109             if ('id' in obj && 'layer' in obj) {
48110                 layers.push(obj);
48111             }
48112         });
48113         dispatch$$1.call('change');
48114         return this;
48115     };
48116
48117
48118     drawLayers.dimensions = function(_) {
48119         if (!arguments.length) return utilGetDimensions(svg);
48120         utilSetDimensions(svg, _);
48121         return this;
48122     };
48123
48124
48125     return utilRebind(drawLayers, dispatch$$1, 'on');
48126 }
48127
48128 function svgLines$$1(projection) {
48129     var detected = utilDetect();
48130
48131     var highway_stack = {
48132         motorway: 0,
48133         motorway_link: 1,
48134         trunk: 2,
48135         trunk_link: 3,
48136         primary: 4,
48137         primary_link: 5,
48138         secondary: 6,
48139         tertiary: 7,
48140         unclassified: 8,
48141         residential: 9,
48142         service: 10,
48143         footway: 11
48144     };
48145
48146     function waystack(a, b) {
48147         var as = 0, bs = 0;
48148         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
48149         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
48150         return as - bs;
48151     }
48152
48153
48154     return function drawLines(selection$$1, graph, entities, filter) {
48155         var ways = [], pathdata = {}, onewaydata = {},
48156             getPath = svgPath(projection, graph);
48157
48158         for (var i = 0; i < entities.length; i++) {
48159             var entity = entities[i],
48160                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
48161             if (outer) {
48162                 ways.push(entity.mergeTags(outer.tags));
48163             } else if (entity.geometry(graph) === 'line') {
48164                 ways.push(entity);
48165             }
48166         }
48167
48168         ways = ways.filter(getPath);
48169
48170         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
48171
48172         lodash.forOwn(pathdata, function(v, k) {
48173             onewaydata[k] = lodash(v)
48174                 .filter(function(d) { return d.isOneWay(); })
48175                 .map(svgOneWaySegments(projection, graph, 35))
48176                 .flatten()
48177                 .valueOf();
48178         });
48179
48180         var layer = selection$$1.selectAll('.layer-lines');
48181
48182         var layergroup = layer
48183             .selectAll('g.layergroup')
48184             .data(sequence(-10, 11));
48185
48186         layergroup = layergroup.enter()
48187             .append('g')
48188             .attr('class', function(d) { return 'layergroup layer' + String(d); })
48189             .merge(layergroup);
48190
48191
48192         var linegroup = layergroup
48193             .selectAll('g.linegroup')
48194             .data(['shadow', 'casing', 'stroke']);
48195
48196         linegroup = linegroup.enter()
48197             .append('g')
48198             .attr('class', function(d) { return 'linegroup line-' + d; })
48199             .merge(linegroup);
48200
48201
48202         var lines = linegroup
48203             .selectAll('path')
48204             .filter(filter)
48205             .data(
48206                 function() { return pathdata[this.parentNode.__data__] || []; },
48207                 osmEntity$$1.key
48208             );
48209
48210         lines.exit()
48211             .remove();
48212
48213         // Optimization: call simple TagClasses only on enter selection. This
48214         // works because osmEntity.key is defined to include the entity v attribute.
48215         lines.enter()
48216             .append('path')
48217             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
48218             .call(svgTagClasses())
48219             .merge(lines)
48220                 .sort(waystack)
48221                 .attr('d', getPath)
48222                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
48223
48224
48225         var onewaygroup = layergroup
48226             .selectAll('g.onewaygroup')
48227             .data(['oneway']);
48228
48229         onewaygroup = onewaygroup.enter()
48230             .append('g')
48231             .attr('class', 'onewaygroup')
48232             .merge(onewaygroup);
48233
48234
48235         var oneways = onewaygroup
48236             .selectAll('path')
48237             .filter(filter)
48238             .data(
48239                 function() { return onewaydata[this.parentNode.__data__] || []; },
48240                 function(d) { return [d.id, d.index]; }
48241             );
48242
48243         oneways.exit()
48244             .remove();
48245
48246         oneways = oneways.enter()
48247             .append('path')
48248             .attr('class', 'oneway')
48249             .attr('marker-mid', 'url(#oneway-marker)')
48250             .merge(oneways)
48251             .attr('d', function(d) { return d.d; });
48252
48253         if (detected.ie) {
48254             oneways.each(function() { this.parentNode.insertBefore(this, this); });
48255         }
48256     };
48257 }
48258
48259 function svgMidpoints$$1(projection, context) {
48260
48261     return function drawMidpoints(selection, graph, entities, filter, extent) {
48262         var poly = extent.polygon(),
48263             midpoints = {};
48264
48265         for (var i = 0; i < entities.length; i++) {
48266             var entity = entities[i];
48267
48268             if (entity.type !== 'way')
48269                 continue;
48270             if (!filter(entity))
48271                 continue;
48272             if (context.selectedIDs().indexOf(entity.id) < 0)
48273                 continue;
48274
48275             var nodes = graph.childNodes(entity);
48276             for (var j = 0; j < nodes.length - 1; j++) {
48277
48278                 var a = nodes[j],
48279                     b = nodes[j + 1],
48280                     id = [a.id, b.id].sort().join('-');
48281
48282                 if (midpoints[id]) {
48283                     midpoints[id].parents.push(entity);
48284                 } else {
48285                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
48286                         var point = geoInterp(a.loc, b.loc, 0.5),
48287                             loc = null;
48288
48289                         if (extent.intersects(point)) {
48290                             loc = point;
48291                         } else {
48292                             for (var k = 0; k < 4; k++) {
48293                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
48294                                 if (point &&
48295                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
48296                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
48297                                 {
48298                                     loc = point;
48299                                     break;
48300                                 }
48301                             }
48302                         }
48303
48304                         if (loc) {
48305                             midpoints[id] = {
48306                                 type: 'midpoint',
48307                                 id: id,
48308                                 loc: loc,
48309                                 edge: [a.id, b.id],
48310                                 parents: [entity]
48311                             };
48312                         }
48313                     }
48314                 }
48315             }
48316         }
48317
48318
48319         function midpointFilter(d) {
48320             if (midpoints[d.id])
48321                 return true;
48322
48323             for (var i = 0; i < d.parents.length; i++) {
48324                 if (filter(d.parents[i])) {
48325                     return true;
48326                 }
48327             }
48328
48329             return false;
48330         }
48331
48332
48333         var layer = selection.selectAll('.layer-hit');
48334
48335         var groups = layer
48336             .selectAll('g.midpoint')
48337             .filter(midpointFilter)
48338             .data(lodash.values(midpoints), function(d) { return d.id; });
48339
48340         groups.exit()
48341             .remove();
48342
48343         var enter = groups.enter()
48344             .insert('g', ':first-child')
48345             .attr('class', 'midpoint');
48346
48347         enter.append('polygon')
48348             .attr('points', '-6,8 10,0 -6,-8')
48349             .attr('class', 'shadow');
48350
48351         enter.append('polygon')
48352             .attr('points', '-3,4 5,0 -3,-4')
48353             .attr('class', 'fill');
48354
48355         groups = groups
48356             .merge(enter)
48357             .attr('transform', function(d) {
48358                 var translate = svgPointTransform(projection),
48359                     a = graph.entity(d.edge[0]),
48360                     b = graph.entity(d.edge[1]),
48361                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
48362                 return translate(d) + ' rotate(' + angleVal + ')';
48363             })
48364             .call(svgTagClasses().tags(
48365                 function(d) { return d.parents[0].tags; }
48366             ));
48367
48368         // Propagate data bindings.
48369         groups.select('polygon.shadow');
48370         groups.select('polygon.fill');
48371
48372     };
48373 }
48374
48375 function svgOneWaySegments(projection, graph, dt) {
48376     return function(entity) {
48377         var a,
48378             b,
48379             i = 0,
48380             offset = dt,
48381             segments = [],
48382             clip = identity$5().clipExtent(projection.clipExtent()).stream,
48383             coordinates = graph.childNodes(entity).map(function(n) {
48384                 return n.loc;
48385             });
48386
48387         if (entity.tags.oneway === '-1') coordinates.reverse();
48388
48389         geoStream({
48390             type: 'LineString',
48391             coordinates: coordinates
48392         }, projection.stream(clip({
48393             lineStart: function() {},
48394             lineEnd: function() {
48395                 a = null;
48396             },
48397             point: function(x, y) {
48398                 b = [x, y];
48399
48400                 if (a) {
48401                     var span = geoEuclideanDistance(a, b) - offset;
48402
48403                     if (span >= 0) {
48404                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
48405                             dx = dt * Math.cos(angle),
48406                             dy = dt * Math.sin(angle),
48407                             p = [a[0] + offset * Math.cos(angle),
48408                                  a[1] + offset * Math.sin(angle)];
48409
48410                         var segment = 'M' + a[0] + ',' + a[1] +
48411                                       'L' + p[0] + ',' + p[1];
48412
48413                         for (span -= dt; span >= 0; span -= dt) {
48414                             p[0] += dx;
48415                             p[1] += dy;
48416                             segment += 'L' + p[0] + ',' + p[1];
48417                         }
48418
48419                         segment += 'L' + b[0] + ',' + b[1];
48420                         segments.push({id: entity.id, index: i, d: segment});
48421                     }
48422
48423                     offset = -span;
48424                     i++;
48425                 }
48426
48427                 a = b;
48428             }
48429         })));
48430
48431         return segments;
48432     };
48433 }
48434
48435 function svgPath(projection, graph, isArea) {
48436
48437     // Explanation of magic numbers:
48438     // "padding" here allows space for strokes to extend beyond the viewport,
48439     // so that the stroke isn't drawn along the edge of the viewport when
48440     // the shape is clipped.
48441     //
48442     // When drawing lines, pad viewport by 5px.
48443     // When drawing areas, pad viewport by 65px in each direction to allow
48444     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
48445
48446     var cache = {},
48447         padding = isArea ? 65 : 5,
48448         viewport = projection.clipExtent(),
48449         paddedExtent = [
48450             [viewport[0][0] - padding, viewport[0][1] - padding],
48451             [viewport[1][0] + padding, viewport[1][1] + padding]
48452         ],
48453         clip = identity$5().clipExtent(paddedExtent).stream,
48454         project = projection.stream,
48455         path$$1 = index$4()
48456             .projection({stream: function(output) { return project(clip(output)); }});
48457
48458     return function(entity) {
48459         if (entity.id in cache) {
48460             return cache[entity.id];
48461         } else {
48462             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
48463         }
48464     };
48465 }
48466
48467 function svgPoints$$1(projection, context) {
48468
48469     function markerPath(selection, klass) {
48470         selection
48471             .attr('class', klass)
48472             .attr('transform', 'translate(-8, -23)')
48473             .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');
48474     }
48475
48476     function sortY(a, b) {
48477         return b.loc[1] - a.loc[1];
48478     }
48479
48480
48481     return function drawPoints(selection, graph, entities, filter) {
48482         var wireframe = context.surface().classed('fill-wireframe'),
48483             points = wireframe ? [] : lodash.filter(entities, function(e) {
48484                 return e.geometry(graph) === 'point';
48485             });
48486
48487         points.sort(sortY);
48488
48489         var layer = selection.selectAll('.layer-hit');
48490
48491         var groups = layer.selectAll('g.point')
48492             .filter(filter)
48493             .data(points, osmEntity$$1.key);
48494
48495         groups.exit()
48496             .remove();
48497
48498         var enter = groups.enter()
48499             .append('g')
48500             .attr('class', function(d) { return 'node point ' + d.id; })
48501             .order();
48502
48503         enter.append('path')
48504             .call(markerPath, 'shadow');
48505
48506         enter.append('path')
48507             .call(markerPath, 'stroke');
48508
48509         enter.append('use')
48510             .attr('transform', 'translate(-5, -19)')
48511             .attr('class', 'icon')
48512             .attr('width', '11px')
48513             .attr('height', '11px');
48514
48515         groups = groups
48516             .merge(enter)
48517             .attr('transform', svgPointTransform(projection))
48518             .call(svgTagClasses());
48519
48520         // Selecting the following implicitly
48521         // sets the data (point entity) on the element
48522         groups.select('.shadow');
48523         groups.select('.stroke');
48524         groups.select('.icon')
48525             .attr('xlink:href', function(entity) {
48526                 var preset = context.presets().match(entity, graph);
48527                 return (preset && preset.icon) ? '#' + preset.icon + '-11' : '';
48528             });
48529     };
48530 }
48531
48532 function svgRelationMemberTags(graph) {
48533     return function(entity) {
48534         var tags = entity.tags;
48535         graph.parentRelations(entity).forEach(function(relation) {
48536             var type = relation.tags.type;
48537             if (type === 'multipolygon' || type === 'boundary') {
48538                 tags = lodash.extend({}, relation.tags, tags);
48539             }
48540         });
48541         return tags;
48542     };
48543 }
48544
48545 function svgTagClasses() {
48546     var primaries = [
48547             'building', 'highway', 'railway', 'waterway', 'aeroway',
48548             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48549             'leisure', 'military', 'place'
48550         ],
48551         statuses = [
48552             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48553             'razed', 'demolished', 'obliterated'
48554         ],
48555         secondaries = [
48556             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48557             'surface', 'tracktype', 'crossing'
48558         ],
48559         tagClassRe = /^tag-/,
48560         tags = function(entity) { return entity.tags; };
48561
48562
48563     var tagClasses = function(selection$$1) {
48564         selection$$1.each(function tagClassesEach(entity) {
48565             var value = this.className,
48566                 classes, primary, status;
48567
48568             if (value.baseVal !== undefined) value = value.baseVal;
48569
48570             classes = value.trim().split(/\s+/).filter(function(name) {
48571                 return name.length && !tagClassRe.test(name);
48572             }).join(' ');
48573
48574             var t = tags(entity), i, k, v;
48575
48576             // pick at most one primary classification tag..
48577             for (i = 0; i < primaries.length; i++) {
48578                 k = primaries[i];
48579                 v = t[k];
48580                 if (!v || v === 'no') continue;
48581
48582                 primary = k;
48583                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48584                     status = v;
48585                     classes += ' tag-' + k;
48586                 } else {
48587                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48588                 }
48589
48590                 break;
48591             }
48592
48593             // add at most one status tag, only if relates to primary tag..
48594             if (!status) {
48595                 for (i = 0; i < statuses.length; i++) {
48596                     k = statuses[i];
48597                     v = t[k];
48598                     if (!v || v === 'no') continue;
48599
48600                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48601                         status = k;
48602                     }
48603                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48604                         status = k;
48605                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48606                         status = k;
48607                         primary = v;
48608                         classes += ' tag-' + v;
48609                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48610
48611                     if (status) break;
48612                 }
48613             }
48614
48615             if (status) {
48616                 classes += ' tag-status tag-status-' + status;
48617             }
48618
48619             // add any secondary (structure) tags
48620             for (i = 0; i < secondaries.length; i++) {
48621                 k = secondaries[i];
48622                 v = t[k];
48623                 if (!v || v === 'no') continue;
48624                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48625             }
48626
48627             // For highways, look for surface tagging..
48628             if (primary === 'highway') {
48629                 var paved = (t.highway !== 'track');
48630                 for (k in t) {
48631                     v = t[k];
48632                     if (k in osmPavedTags) {
48633                         paved = !!osmPavedTags[k][v];
48634                         break;
48635                     }
48636                 }
48637                 if (!paved) {
48638                     classes += ' tag-unpaved';
48639                 }
48640             }
48641
48642             classes = classes.trim();
48643
48644             if (classes !== value) {
48645                 select(this).attr('class', classes);
48646             }
48647         });
48648     };
48649
48650
48651     tagClasses.tags = function(_) {
48652         if (!arguments.length) return tags;
48653         tags = _;
48654         return tagClasses;
48655     };
48656
48657     return tagClasses;
48658 }
48659
48660 function svgTurns(projection) {
48661
48662     return function drawTurns(selection, graph, turns) {
48663
48664         function key(turn) {
48665             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48666         }
48667
48668         function icon(turn) {
48669             var u = turn.u ? '-u' : '';
48670             if (!turn.restriction)
48671                 return '#turn-yes' + u;
48672             var restriction = graph.entity(turn.restriction).tags.restriction;
48673             return '#turn-' +
48674                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48675         }
48676
48677         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48678             .data(turns, key);
48679
48680         groups.exit()
48681             .remove();
48682
48683
48684         var enter = groups.enter()
48685             .append('g')
48686             .attr('class', 'turn');
48687
48688         var nEnter = enter
48689             .filter(function (turn) { return !turn.u; });
48690
48691         nEnter.append('rect')
48692             .attr('transform', 'translate(-22, -12)')
48693             .attr('width', '44')
48694             .attr('height', '24');
48695
48696         nEnter.append('use')
48697             .attr('transform', 'translate(-22, -12)')
48698             .attr('width', '44')
48699             .attr('height', '24');
48700
48701
48702         var uEnter = enter
48703             .filter(function (turn) { return turn.u; });
48704
48705         uEnter.append('circle')
48706             .attr('r', '16');
48707
48708         uEnter.append('use')
48709             .attr('transform', 'translate(-16, -16)')
48710             .attr('width', '32')
48711             .attr('height', '32');
48712
48713
48714         groups = groups
48715             .merge(enter);
48716
48717         groups
48718             .attr('transform', function (turn) {
48719                 var v = graph.entity(turn.via.node),
48720                     t = graph.entity(turn.to.node),
48721                     a = geoAngle(v, t, projection),
48722                     p = projection(v.loc),
48723                     r = turn.u ? 0 : 60;
48724
48725                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48726                     'rotate(' + a * 180 / Math.PI + ')';
48727             });
48728
48729         groups.select('use')
48730             .attr('xlink:href', icon);
48731
48732         groups.select('rect');
48733         groups.select('circle');
48734
48735         return this;
48736     };
48737 }
48738
48739 function svgVertices$$1(projection, context) {
48740     var radiuses = {
48741         //       z16-, z17, z18+, tagged
48742         shadow: [6,    7.5,   7.5,  11.5],
48743         stroke: [2.5,  3.5,   3.5,  7],
48744         fill:   [1,    1.5,   1.5,  1.5]
48745     };
48746
48747     var hover;
48748
48749
48750     function siblingAndChildVertices(ids, graph, extent$$1) {
48751         var vertices = {};
48752
48753         function addChildVertices(entity) {
48754             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48755                 var i;
48756                 if (entity.type === 'way') {
48757                     for (i = 0; i < entity.nodes.length; i++) {
48758                         addChildVertices(graph.entity(entity.nodes[i]));
48759                     }
48760                 } else if (entity.type === 'relation') {
48761                     for (i = 0; i < entity.members.length; i++) {
48762                         var member = context.hasEntity(entity.members[i].id);
48763                         if (member) {
48764                             addChildVertices(member);
48765                         }
48766                     }
48767                 } else if (entity.intersects(extent$$1, graph)) {
48768                     vertices[entity.id] = entity;
48769                 }
48770             }
48771         }
48772
48773         ids.forEach(function(id) {
48774             var entity = context.hasEntity(id);
48775             if (entity && entity.type === 'node') {
48776                 vertices[entity.id] = entity;
48777                 context.graph().parentWays(entity).forEach(function(entity) {
48778                     addChildVertices(entity);
48779                 });
48780             } else if (entity) {
48781                 addChildVertices(entity);
48782             }
48783         });
48784
48785         return vertices;
48786     }
48787
48788
48789     function draw(selection$$1, vertices, klass, graph, zoom$$1, siblings) {
48790
48791         function icon(entity) {
48792             if (entity.id in icons) return icons[entity.id];
48793             icons[entity.id] =
48794                 entity.hasInterestingTags() &&
48795                 context.presets().match(entity, graph).icon;
48796             return icons[entity.id];
48797         }
48798
48799         function setClass(klass) {
48800             return function(entity) {
48801                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48802             };
48803         }
48804
48805         function setAttributes(selection$$1) {
48806             ['shadow','stroke','fill'].forEach(function(klass) {
48807                 var rads = radiuses[klass];
48808                 selection$$1.selectAll('.' + klass)
48809                     .each(function(entity) {
48810                         var i = z && icon(entity),
48811                             c = i ? 0.5 : 0,
48812                             r = rads[i ? 3 : z];
48813
48814                         // slightly increase the size of unconnected endpoints #3775
48815                         if (entity.isEndpoint(graph) && !entity.isConnected(graph)) {
48816                             r += 1.5;
48817                         }
48818
48819                         this.setAttribute('cx', c);
48820                         this.setAttribute('cy', -c);
48821                         this.setAttribute('r', r);
48822                         if (i && klass === 'fill') {
48823                             this.setAttribute('visibility', 'hidden');
48824                         } else {
48825                             this.removeAttribute('visibility');
48826                         }
48827                     });
48828             });
48829
48830             selection$$1.selectAll('use')
48831                 .each(function() {
48832                     if (z) {
48833                         this.removeAttribute('visibility');
48834                     } else {
48835                         this.setAttribute('visibility', 'hidden');
48836                     }
48837                 });
48838         }
48839
48840
48841         siblings = siblings || {};
48842
48843         var icons = {},
48844             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48845
48846         var groups = selection$$1
48847             .data(vertices, osmEntity$$1.key);
48848
48849         groups.exit()
48850             .remove();
48851
48852         var enter = groups.enter()
48853             .append('g')
48854             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48855
48856         enter.append('circle')
48857             .each(setClass('shadow'));
48858
48859         enter.append('circle')
48860             .each(setClass('stroke'));
48861
48862         // Vertices with icons get a `use`.
48863         enter.filter(function(d) { return icon(d); })
48864             .append('use')
48865             .attr('transform', 'translate(-5, -6)')
48866             .attr('xlink:href', function(d) { return '#' + icon(d) + '-11'; })
48867             .attr('width', '11px')
48868             .attr('height', '11px')
48869             .each(setClass('icon'));
48870
48871         // Vertices with tags get a fill.
48872         enter.filter(function(d) { return d.hasInterestingTags(); })
48873             .append('circle')
48874             .each(setClass('fill'));
48875
48876         groups
48877             .merge(enter)
48878             .attr('transform', svgPointTransform(projection))
48879             .classed('sibling', function(entity) { return entity.id in siblings; })
48880             .classed('shared', function(entity) { return graph.isShared(entity); })
48881             .classed('endpoint', function(entity) { return entity.isEndpoint(graph); })
48882             .call(setAttributes);
48883     }
48884
48885
48886     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48887         var siblings = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48888             wireframe = context.surface().classed('fill-wireframe'),
48889             vertices = [];
48890
48891         for (var i = 0; i < entities.length; i++) {
48892             var entity = entities[i],
48893                 geometry = entity.geometry(graph);
48894
48895             if (wireframe && geometry === 'point') {
48896                 vertices.push(entity);
48897                 continue;
48898             }
48899
48900             if (geometry !== 'vertex')
48901                 continue;
48902
48903             if (entity.id in siblings ||
48904                 entity.hasInterestingTags() ||
48905                 entity.isEndpoint(graph) ||
48906                 entity.isConnected(graph)) {
48907                 vertices.push(entity);
48908             }
48909         }
48910
48911         var layer = selection$$1.selectAll('.layer-hit');
48912         layer.selectAll('g.vertex.vertex-persistent')
48913             .filter(filter)
48914             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1, siblings);
48915
48916         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48917     }
48918
48919
48920     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48921         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48922         var layer = selection$$1.selectAll('.layer-hit');
48923
48924         layer.selectAll('g.vertex.vertex-hover')
48925             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48926     }
48927
48928
48929     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48930         if (target === hover) return;
48931         hover = target;
48932         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48933     };
48934
48935     return drawVertices;
48936 }
48937
48938 function behaviorEdit(context) {
48939
48940     function edit() {
48941         context.map()
48942             .minzoom(context.minEditableZoom());
48943     }
48944
48945
48946     edit.off = function() {
48947         context.map()
48948             .minzoom(0);
48949     };
48950
48951
48952     return edit;
48953 }
48954
48955 /*
48956    The hover behavior adds the `.hover` class on mouseover to all elements to which
48957    the identical datum is bound, and removes it on mouseout.
48958
48959    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
48960    representation may consist of several elements scattered throughout the DOM hierarchy.
48961    Only one of these elements can have the :hover pseudo-class, but all of them will
48962    have the .hover class.
48963  */
48964 function behaviorHover() {
48965     var dispatch$$1 = dispatch('hover'),
48966         selection$$1 = select(null),
48967         buttonDown,
48968         altDisables,
48969         target;
48970
48971
48972     function keydown() {
48973         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48974             dispatch$$1.call('hover', this, null);
48975             selection$$1.selectAll('.hover')
48976                 .classed('hover-suppressed', true)
48977                 .classed('hover', false);
48978         }
48979     }
48980
48981
48982     function keyup() {
48983         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48984             dispatch$$1.call('hover', this, target ? target.id : null);
48985             selection$$1.selectAll('.hover-suppressed')
48986                 .classed('hover-suppressed', false)
48987                 .classed('hover', true);
48988         }
48989     }
48990
48991
48992     var hover = function(__) {
48993         selection$$1 = __;
48994
48995         selection$$1
48996             .on('mouseover.hover', mouseover)
48997             .on('mouseout.hover', mouseout)
48998             .on('mousedown.hover', mousedown);
48999
49000         select(window)
49001             .on('keydown.hover', keydown)
49002             .on('keyup.hover', keyup);
49003
49004
49005         function mouseover() {
49006             if (buttonDown) return;
49007             var target = event.target;
49008             enter(target ? target.__data__ : null);
49009         }
49010
49011
49012         function mouseout() {
49013             if (buttonDown) return;
49014             var target = event.relatedTarget;
49015             enter(target ? target.__data__ : null);
49016         }
49017
49018
49019         function mousedown() {
49020             buttonDown = true;
49021             select(window)
49022                 .on('mouseup.hover', mouseup, true);
49023         }
49024
49025
49026         function mouseup() {
49027             buttonDown = false;
49028             select(window)
49029                 .on('mouseup.hover', null, true);
49030         }
49031
49032
49033         function enter(d) {
49034             if (d === target) return;
49035             target = d;
49036
49037             selection$$1.selectAll('.hover')
49038                 .classed('hover', false);
49039             selection$$1.selectAll('.hover-suppressed')
49040                 .classed('hover-suppressed', false);
49041
49042             if (target instanceof osmEntity$$1) {
49043                 var selector$$1 = '.' + target.id;
49044
49045                 if (target.type === 'relation') {
49046                     target.members.forEach(function(member) {
49047                         selector$$1 += ', .' + member.id;
49048                     });
49049                 }
49050
49051                 var suppressed = altDisables && event && event.altKey;
49052
49053                 selection$$1.selectAll(selector$$1)
49054                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
49055
49056                 dispatch$$1.call('hover', this, target.id);
49057             } else {
49058                 dispatch$$1.call('hover', this, null);
49059             }
49060         }
49061
49062     };
49063
49064
49065     hover.off = function(selection$$1) {
49066         selection$$1.selectAll('.hover')
49067             .classed('hover', false);
49068         selection$$1.selectAll('.hover-suppressed')
49069             .classed('hover-suppressed', false);
49070
49071         selection$$1
49072             .on('mouseover.hover', null)
49073             .on('mouseout.hover', null)
49074             .on('mousedown.hover', null);
49075
49076         select(window)
49077             .on('keydown.hover', null)
49078             .on('keyup.hover', null);
49079     };
49080
49081
49082     hover.altDisables = function(_) {
49083         if (!arguments.length) return altDisables;
49084         altDisables = _;
49085         return hover;
49086     };
49087
49088
49089     return utilRebind(hover, dispatch$$1, 'on');
49090 }
49091
49092 function behaviorTail() {
49093     var text$$1,
49094         container,
49095         xmargin = 25,
49096         tooltipSize = [0, 0],
49097         selectionSize = [0, 0];
49098
49099
49100     function tail(selection$$1) {
49101         if (!text$$1) return;
49102
49103         select(window)
49104             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
49105
49106         container = select(document.body)
49107             .append('div')
49108             .style('display', 'none')
49109             .attr('class', 'tail tooltip-inner');
49110
49111         container.append('div')
49112             .text(text$$1);
49113
49114         selection$$1
49115             .on('mousemove.tail', mousemove)
49116             .on('mouseenter.tail', mouseenter)
49117             .on('mouseleave.tail', mouseleave);
49118
49119         container
49120             .on('mousemove.tail', mousemove);
49121
49122         tooltipSize = utilGetDimensions(container);
49123         selectionSize = utilGetDimensions(selection$$1);
49124
49125
49126         function show() {
49127             container.style('display', 'block');
49128             tooltipSize = utilGetDimensions(container);
49129         }
49130
49131
49132         function mousemove() {
49133             if (container.style('display') === 'none') show();
49134             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
49135                 -tooltipSize[0] - xmargin : xmargin;
49136             container.classed('left', xoffset > 0);
49137             utilSetTransform(container, event.clientX + xoffset, event.clientY);
49138         }
49139
49140
49141         function mouseleave() {
49142             if (event.relatedTarget !== container.node()) {
49143                 container.style('display', 'none');
49144             }
49145         }
49146
49147
49148         function mouseenter() {
49149             if (event.relatedTarget !== container.node()) {
49150                 show();
49151             }
49152         }
49153     }
49154
49155
49156     tail.off = function(selection$$1) {
49157         if (!text$$1) return;
49158
49159         container
49160             .on('mousemove.tail', null)
49161             .remove();
49162
49163         selection$$1
49164             .on('mousemove.tail', null)
49165             .on('mouseenter.tail', null)
49166             .on('mouseleave.tail', null);
49167
49168         select(window)
49169             .on('resize.tail', null);
49170     };
49171
49172
49173     tail.text = function(_) {
49174         if (!arguments.length) return text$$1;
49175         text$$1 = _;
49176         return tail;
49177     };
49178
49179
49180     return tail;
49181 }
49182
49183 behaviorDraw.usedTails = {};
49184 behaviorDraw.disableSpace = false;
49185 behaviorDraw.lastSpace = null;
49186
49187
49188 function behaviorDraw(context) {
49189     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
49190             'clickNode', 'undo', 'cancel', 'finish'),
49191         keybinding = d3keybinding('draw'),
49192         hover = behaviorHover(context)
49193             .altDisables(true)
49194             .on('hover', context.ui().sidebar.hover),
49195         tail = behaviorTail(),
49196         edit = behaviorEdit(context),
49197         closeTolerance = 4,
49198         tolerance = 12,
49199         mouseLeave = false,
49200         lastMouse = null,
49201         cached = behaviorDraw;
49202
49203
49204     function datum() {
49205         if (event.altKey) return {};
49206
49207         if (event.type === 'keydown') {
49208             return (lastMouse && lastMouse.target.__data__) || {};
49209         } else {
49210             return event.target.__data__ || {};
49211         }
49212     }
49213
49214
49215     function mousedown() {
49216
49217         function point() {
49218             var p = context.container().node();
49219             return touchId !== null ? touches(p).filter(function(p) {
49220                 return p.identifier === touchId;
49221             })[0] : mouse(p);
49222         }
49223
49224         var element = select(this),
49225             touchId = event.touches ? event.changedTouches[0].identifier : null,
49226             t1 = +new Date(),
49227             p1 = point();
49228
49229         element.on('mousemove.draw', null);
49230
49231         select(window).on('mouseup.draw', function() {
49232             var t2 = +new Date(),
49233                 p2 = point(),
49234                 dist = geoEuclideanDistance(p1, p2);
49235
49236             element.on('mousemove.draw', mousemove);
49237             select(window).on('mouseup.draw', null);
49238
49239             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
49240                 // Prevent a quick second click
49241                 select(window).on('click.draw-block', function() {
49242                     event.stopPropagation();
49243                 }, true);
49244
49245                 context.map().dblclickEnable(false);
49246
49247                 window.setTimeout(function() {
49248                     context.map().dblclickEnable(true);
49249                     select(window).on('click.draw-block', null);
49250                 }, 500);
49251
49252                 click();
49253             }
49254         }, true);
49255     }
49256
49257
49258     function mousemove() {
49259         lastMouse = event;
49260         dispatch$$1.call('move', this, datum());
49261     }
49262
49263
49264     function mouseenter() {
49265         mouseLeave = false;
49266     }
49267
49268
49269     function mouseleave() {
49270         mouseLeave = true;
49271     }
49272
49273
49274     function click() {
49275         var d = datum();
49276         if (d.type === 'way') {
49277             var dims = context.map().dimensions(),
49278                 mouse$$1 = context.mouse(),
49279                 pad = 5,
49280                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
49281                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
49282
49283             if (trySnap) {
49284                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
49285                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
49286                 dispatch$$1.call('clickWay', this, choice.loc, edge);
49287             } else {
49288                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
49289             }
49290
49291         } else if (d.type === 'node') {
49292             dispatch$$1.call('clickNode', this, d);
49293
49294         } else {
49295             dispatch$$1.call('click', this, context.map().mouseCoordinates());
49296         }
49297     }
49298
49299
49300     function space() {
49301         var currSpace = context.mouse();
49302         if (cached.disableSpace && cached.lastSpace) {
49303             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
49304             if (dist > tolerance) {
49305                 cached.disableSpace = false;
49306             }
49307         }
49308
49309         if (cached.disableSpace || mouseLeave || !lastMouse) return;
49310
49311         // user must move mouse or release space bar to allow another click
49312         cached.lastSpace = currSpace;
49313         cached.disableSpace = true;
49314
49315         select(window).on('keyup.space-block', function() {
49316             cached.disableSpace = false;
49317             select(window).on('keyup.space-block', null);
49318         });
49319
49320         event.preventDefault();
49321         click();
49322     }
49323
49324
49325     function backspace() {
49326         event.preventDefault();
49327         dispatch$$1.call('undo');
49328     }
49329
49330
49331     function del() {
49332         event.preventDefault();
49333         dispatch$$1.call('cancel');
49334     }
49335
49336
49337     function ret() {
49338         event.preventDefault();
49339         dispatch$$1.call('finish');
49340     }
49341
49342
49343     function draw(selection$$1) {
49344         context.install(hover);
49345         context.install(edit);
49346
49347         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49348             context.install(tail);
49349         }
49350
49351         keybinding
49352             .on('⌫', backspace)
49353             .on('⌦', del)
49354             .on('⎋', ret)
49355             .on('↩', ret)
49356             .on('space', space)
49357             .on('⌥space', space);
49358
49359         selection$$1
49360             .on('mouseenter.draw', mouseenter)
49361             .on('mouseleave.draw', mouseleave)
49362             .on('mousedown.draw', mousedown)
49363             .on('mousemove.draw', mousemove);
49364
49365         select(document)
49366             .call(keybinding);
49367
49368         return draw;
49369     }
49370
49371
49372     draw.off = function(selection$$1) {
49373         context.ui().sidebar.hover.cancel();
49374         context.uninstall(hover);
49375         context.uninstall(edit);
49376
49377         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
49378             context.uninstall(tail);
49379             cached.usedTails[tail.text()] = true;
49380         }
49381
49382         selection$$1
49383             .on('mouseenter.draw', null)
49384             .on('mouseleave.draw', null)
49385             .on('mousedown.draw', null)
49386             .on('mousemove.draw', null);
49387
49388         select(window)
49389             .on('mouseup.draw', null);
49390             // note: keyup.space-block, click.draw-block should remain
49391
49392         select(document)
49393             .call(keybinding.off);
49394     };
49395
49396
49397     draw.tail = function(_) {
49398         tail.text(_);
49399         return draw;
49400     };
49401
49402
49403     return utilRebind(draw, dispatch$$1, 'on');
49404 }
49405
49406 function behaviorAddWay(context) {
49407     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
49408         draw = behaviorDraw(context);
49409
49410     var addWay = function(surface) {
49411         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
49412             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
49413             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
49414             .on('cancel', addWay.cancel)
49415             .on('finish', addWay.cancel);
49416
49417         context.map()
49418             .dblclickEnable(false);
49419
49420         surface.call(draw);
49421     };
49422
49423
49424     addWay.off = function(surface) {
49425         surface.call(draw.off);
49426     };
49427
49428
49429     addWay.cancel = function() {
49430         window.setTimeout(function() {
49431             context.map().dblclickEnable(true);
49432         }, 1000);
49433
49434         context.enter(modeBrowse(context));
49435     };
49436
49437
49438     addWay.tail = function(text$$1) {
49439         draw.tail(text$$1);
49440         return addWay;
49441     };
49442
49443
49444     return utilRebind(addWay, dispatch$$1, 'on');
49445 }
49446
49447 function behaviorBreathe() {
49448     var duration = 800,
49449         steps = 4,
49450         selector$$1 = '.selected.shadow, .selected .shadow',
49451         selected = select(null),
49452         classed = '',
49453         params = {},
49454         done = false,
49455         timer$$1;
49456
49457
49458     function ratchetyInterpolator(a, b, steps, units) {
49459         a = parseFloat(a);
49460         b = parseFloat(b);
49461         var sample = quantize$2()
49462             .domain([0, 1])
49463             .range(quantize$1(number$1(a, b), steps));
49464
49465         return function(t) {
49466             return String(sample(t)) + (units || '');
49467         };
49468     }
49469
49470
49471     function reset(selection$$1) {
49472         selection$$1
49473             .style('stroke-opacity', null)
49474             .style('stroke-width', null)
49475             .style('fill-opacity', null)
49476             .style('r', null);
49477     }
49478
49479
49480     function setAnimationParams(transition$$1, fromTo) {
49481         var toFrom = (fromTo === 'from' ? 'to' : 'from');
49482
49483         transition$$1
49484             .styleTween('stroke-opacity', function(d) {
49485                 return ratchetyInterpolator(
49486                     params[d.id][toFrom].opacity,
49487                     params[d.id][fromTo].opacity,
49488                     steps
49489                 );
49490             })
49491             .styleTween('stroke-width', function(d) {
49492                 return ratchetyInterpolator(
49493                     params[d.id][toFrom].width,
49494                     params[d.id][fromTo].width,
49495                     steps,
49496                     'px'
49497                 );
49498             })
49499             .styleTween('fill-opacity', function(d) {
49500                 return ratchetyInterpolator(
49501                     params[d.id][toFrom].opacity,
49502                     params[d.id][fromTo].opacity,
49503                     steps
49504                 );
49505             })
49506             .styleTween('r', function(d) {
49507                 return ratchetyInterpolator(
49508                     params[d.id][toFrom].width,
49509                     params[d.id][fromTo].width,
49510                     steps,
49511                     'px'
49512                 );
49513             });
49514     }
49515
49516
49517     function calcAnimationParams(selection$$1) {
49518         selection$$1
49519             .call(reset)
49520             .each(function(d) {
49521                 var s = select(this),
49522                     tag = s.node().tagName,
49523                     p = {'from': {}, 'to': {}},
49524                     opacity, width;
49525
49526                 // determine base opacity and width
49527                 if (tag === 'circle') {
49528                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
49529                     width = parseFloat(s.style('r') || 15.5);
49530                 } else {
49531                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49532                     width = parseFloat(s.style('stroke-width') || 10);
49533                 }
49534
49535                 // calculate from/to interpolation params..
49536                 p.tag = tag;
49537                 p.from.opacity = opacity * 0.6;
49538                 p.to.opacity = opacity * 1.25;
49539                 p.from.width = width * 0.9;
49540                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
49541                 params[d.id] = p;
49542             });
49543     }
49544
49545
49546     function run(surface, fromTo) {
49547         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49548             currSelected = surface.selectAll(selector$$1),
49549             currClassed = surface.attr('class');
49550
49551         if (done || currSelected.empty()) {
49552             selected.call(reset);
49553             return;
49554         }
49555
49556         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49557             selected.call(reset);
49558             classed = currClassed;
49559             selected = currSelected.call(calcAnimationParams);
49560         }
49561
49562         selected
49563             .transition()
49564             .duration(duration)
49565             .call(setAnimationParams, fromTo)
49566             .on('end', function() {
49567                 surface.call(run, toFrom);
49568             });
49569     }
49570
49571
49572     var breathe = function(surface) {
49573         done = false;
49574         timer$$1 = timer$1(function() {
49575             // wait for elements to actually become selected
49576             if (surface.selectAll(selector$$1).empty()) {
49577                 return false;
49578             }
49579
49580             surface.call(run, 'from');
49581             timer$$1.stop();
49582             return true;
49583         }, 20);
49584     };
49585
49586
49587     breathe.off = function() {
49588         done = true;
49589         if (timer$$1) {
49590             timer$$1.stop();
49591         }
49592         selected
49593             .interrupt()
49594             .call(reset);
49595     };
49596
49597
49598     return breathe;
49599 }
49600
49601 function behaviorCopy(context) {
49602     var keybinding = d3keybinding('copy');
49603
49604
49605     function groupEntities(ids, graph) {
49606         var entities = ids.map(function (id) { return graph.entity(id); });
49607         return lodash.extend({relation: [], way: [], node: []},
49608             lodash.groupBy(entities, function(entity) { return entity.type; }));
49609     }
49610
49611
49612     function getDescendants(id, graph, descendants) {
49613         var entity = graph.entity(id),
49614             i, children;
49615
49616         descendants = descendants || {};
49617
49618         if (entity.type === 'relation') {
49619             children = lodash.map(entity.members, 'id');
49620         } else if (entity.type === 'way') {
49621             children = entity.nodes;
49622         } else {
49623             children = [];
49624         }
49625
49626         for (i = 0; i < children.length; i++) {
49627             if (!descendants[children[i]]) {
49628                 descendants[children[i]] = true;
49629                 descendants = getDescendants(children[i], graph, descendants);
49630             }
49631         }
49632
49633         return descendants;
49634     }
49635
49636
49637     function doCopy() {
49638         event.preventDefault();
49639         if (context.inIntro()) return;
49640
49641         var graph = context.graph(),
49642             selected = groupEntities(context.selectedIDs(), graph),
49643             canCopy = [],
49644             skip = {},
49645             i, entity;
49646
49647         for (i = 0; i < selected.relation.length; i++) {
49648             entity = selected.relation[i];
49649             if (!skip[entity.id] && entity.isComplete(graph)) {
49650                 canCopy.push(entity.id);
49651                 skip = getDescendants(entity.id, graph, skip);
49652             }
49653         }
49654         for (i = 0; i < selected.way.length; i++) {
49655             entity = selected.way[i];
49656             if (!skip[entity.id]) {
49657                 canCopy.push(entity.id);
49658                 skip = getDescendants(entity.id, graph, skip);
49659             }
49660         }
49661         for (i = 0; i < selected.node.length; i++) {
49662             entity = selected.node[i];
49663             if (!skip[entity.id]) {
49664                 canCopy.push(entity.id);
49665             }
49666         }
49667
49668         context.copyIDs(canCopy);
49669     }
49670
49671
49672     function copy() {
49673         keybinding.on(uiCmd('⌘C'), doCopy);
49674         select(document).call(keybinding);
49675         return copy;
49676     }
49677
49678
49679     copy.off = function() {
49680         select(document).call(keybinding.off);
49681     };
49682
49683
49684     return copy;
49685 }
49686
49687 /*
49688     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49689
49690     * The `origin` function is expected to return an [x, y] tuple rather than an
49691       {x, y} object.
49692     * The events are `start`, `move`, and `end`.
49693       (https://github.com/mbostock/d3/issues/563)
49694     * The `start` event is not dispatched until the first cursor movement occurs.
49695       (https://github.com/mbostock/d3/pull/368)
49696     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49697       than `x`, `y`, `dx`, and `dy` properties.
49698     * The `end` event is not dispatched if no movement occurs.
49699     * An `off` function is available that unbinds the drag's internal event handlers.
49700     * Delegation is supported via the `delegate` function.
49701
49702  */
49703 function behaviorDrag() {
49704     var event$$1 = dispatch('start', 'move', 'end'),
49705         origin = null,
49706         selector$$1 = '',
49707         filter = null,
49708         event_, target, surface;
49709
49710
49711     function d3_eventCancel() {
49712         event.stopPropagation();
49713         event.preventDefault();
49714     }
49715
49716     function eventOf(thiz, argumentz) {
49717         return function(e1) {
49718             e1.target = drag$$1;
49719             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49720         };
49721     }
49722
49723     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49724         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49725             function () {
49726                 var selection$$1 = selection(),
49727                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49728                 selection$$1.style(d3_event_userSelectProperty, 'none');
49729                 return function () {
49730                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49731                 };
49732             } :
49733             function (type) {
49734                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49735                 return function () {
49736                     w.on('selectstart.' + type, null);
49737                 };
49738             };
49739
49740
49741     function dragstart() {
49742         target = this;
49743         event_ = eventOf(target, arguments);
49744
49745         var eventTarget = event.target,
49746             touchId = event.touches ? event.changedTouches[0].identifier : null,
49747             offset,
49748             origin_ = point(),
49749             started = false,
49750             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49751
49752         var w = select(window)
49753             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49754             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49755
49756         if (origin) {
49757             offset = origin.apply(target, arguments);
49758             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49759         } else {
49760             offset = [0, 0];
49761         }
49762
49763         if (touchId === null) event.stopPropagation();
49764
49765
49766         function point() {
49767             var p = surface || target.parentNode;
49768             return touchId !== null ? touches(p).filter(function(p) {
49769                 return p.identifier === touchId;
49770             })[0] : mouse(p);
49771         }
49772
49773
49774         function dragmove() {
49775             var p = point(),
49776                 dx = p[0] - origin_[0],
49777                 dy = p[1] - origin_[1];
49778
49779             if (dx === 0 && dy === 0)
49780                 return;
49781
49782             if (!started) {
49783                 started = true;
49784                 event_({
49785                     type: 'start'
49786                 });
49787             }
49788
49789             origin_ = p;
49790             d3_eventCancel();
49791
49792             event_({
49793                 type: 'move',
49794                 point: [p[0] + offset[0],  p[1] + offset[1]],
49795                 delta: [dx, dy]
49796             });
49797         }
49798
49799
49800         function dragend() {
49801             if (started) {
49802                 event_({
49803                     type: 'end'
49804                 });
49805
49806                 d3_eventCancel();
49807                 if (event.target === eventTarget) w.on('click.drag', click, true);
49808             }
49809
49810             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49811                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49812             selectEnable();
49813         }
49814
49815
49816         function click() {
49817             d3_eventCancel();
49818             w.on('click.drag', null);
49819         }
49820     }
49821
49822
49823     function drag$$1(selection$$1) {
49824         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49825             delegate = dragstart;
49826
49827         if (selector$$1) {
49828             delegate = function() {
49829                 var root = this,
49830                     target = event.target;
49831                 for (; target && target !== root; target = target.parentNode) {
49832                     if (target[matchesSelector](selector$$1) &&
49833                             (!filter || filter(target.__data__))) {
49834                         return dragstart.call(target, target.__data__);
49835                     }
49836                 }
49837             };
49838         }
49839
49840         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49841             .on('touchstart.drag' + selector$$1, delegate);
49842     }
49843
49844
49845     drag$$1.off = function(selection$$1) {
49846         selection$$1.on('mousedown.drag' + selector$$1, null)
49847             .on('touchstart.drag' + selector$$1, null);
49848     };
49849
49850
49851     drag$$1.delegate = function(_) {
49852         if (!arguments.length) return selector$$1;
49853         selector$$1 = _;
49854         return drag$$1;
49855     };
49856
49857
49858     drag$$1.filter = function(_) {
49859         if (!arguments.length) return origin;
49860         filter = _;
49861         return drag$$1;
49862     };
49863
49864
49865     drag$$1.origin = function (_) {
49866         if (!arguments.length) return origin;
49867         origin = _;
49868         return drag$$1;
49869     };
49870
49871
49872     drag$$1.cancel = function() {
49873         select(window)
49874             .on('mousemove.drag', null)
49875             .on('mouseup.drag', null);
49876         return drag$$1;
49877     };
49878
49879
49880     drag$$1.target = function() {
49881         if (!arguments.length) return target;
49882         target = arguments[0];
49883         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49884         return drag$$1;
49885     };
49886
49887
49888     drag$$1.surface = function() {
49889         if (!arguments.length) return surface;
49890         surface = arguments[0];
49891         return drag$$1;
49892     };
49893
49894
49895     return utilRebind(drag$$1, event$$1, 'on');
49896 }
49897
49898 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49899
49900     var way = context.entity(wayId),
49901         isArea = context.geometry(wayId) === 'area',
49902         finished = false,
49903         annotation = t((way.isDegenerate() ?
49904             'operations.start.annotation.' :
49905             'operations.continue.annotation.') + context.geometry(wayId)),
49906         draw = behaviorDraw(context),
49907         startIndex, start, end, segment;
49908
49909
49910     if (!isArea) {
49911         startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0;
49912         start = osmNode({ id: 'nStart', loc: context.entity(way.nodes[startIndex]).loc });
49913         end = osmNode({ id: 'nEnd', loc: context.map().mouseCoordinates() });
49914         segment = osmWay({ id: 'wTemp',
49915             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49916             tags: lodash.clone(way.tags)
49917         });
49918     } else {
49919         end = osmNode({ loc: context.map().mouseCoordinates() });
49920     }
49921
49922
49923     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49924     if (isArea) {
49925         fn(actionAddEntity(end),
49926             actionAddVertex(wayId, end.id)
49927         );
49928     } else {
49929         fn(actionAddEntity(start),
49930             actionAddEntity(end),
49931             actionAddEntity(segment)
49932         );
49933     }
49934
49935
49936     function move(datum) {
49937         var loc;
49938
49939         if (datum.type === 'node' && datum.id !== end.id) {
49940             loc = datum.loc;
49941
49942         } else if (datum.type === 'way') { // && (segment || datum.id !== segment.id)) {
49943             var dims = context.map().dimensions(),
49944                 mouse = context.mouse(),
49945                 pad = 5,
49946                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49947                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49948
49949             if (trySnap) {
49950                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
49951             }
49952         }
49953
49954         if (!loc) {
49955             loc = context.map().mouseCoordinates();
49956         }
49957
49958         context.replace(actionMoveNode(end.id, loc));
49959     }
49960
49961
49962     function undone() {
49963         finished = true;
49964         context.enter(modeBrowse(context));
49965     }
49966
49967
49968     function setActiveElements() {
49969         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
49970         context.surface().selectAll(utilEntitySelector(active))
49971             .classed('active', true);
49972     }
49973
49974
49975     var drawWay = function(surface) {
49976         draw.on('move', move)
49977             .on('click', drawWay.add)
49978             .on('clickWay', drawWay.addWay)
49979             .on('clickNode', drawWay.addNode)
49980             .on('undo', context.undo)
49981             .on('cancel', drawWay.cancel)
49982             .on('finish', drawWay.finish);
49983
49984         context.map()
49985             .dblclickEnable(false)
49986             .on('drawn.draw', setActiveElements);
49987
49988         setActiveElements();
49989
49990         surface.call(draw);
49991
49992         context.history()
49993             .on('undone.draw', undone);
49994     };
49995
49996
49997     drawWay.off = function(surface) {
49998         if (!finished)
49999             context.pop();
50000
50001         context.map()
50002             .on('drawn.draw', null);
50003
50004         surface.call(draw.off)
50005             .selectAll('.active')
50006             .classed('active', false);
50007
50008         context.history()
50009             .on('undone.draw', null);
50010     };
50011
50012
50013     function ReplaceTemporaryNode(newNode) {
50014         return function(graph) {
50015             if (isArea) {
50016                 return graph
50017                     .replace(way.addNode(newNode.id))
50018                     .remove(end);
50019             } else {
50020                 return graph
50021                     .replace(graph.entity(wayId).addNode(newNode.id, index))
50022                     .remove(end)
50023                     .remove(segment)
50024                     .remove(start);
50025             }
50026         };
50027     }
50028
50029
50030     // Accept the current position of the temporary node and continue drawing.
50031     drawWay.add = function(loc) {
50032         // prevent duplicate nodes
50033         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
50034         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
50035
50036         if (isArea) {
50037             context.replace(
50038                 actionMoveNode(end.id, loc),
50039                 annotation
50040             );
50041         } else {
50042             var newNode = osmNode({loc: loc});
50043             context.replace(
50044                 actionAddEntity(newNode),
50045                 ReplaceTemporaryNode(newNode),
50046                 annotation
50047             );
50048         }
50049
50050         finished = true;
50051         context.enter(mode);
50052     };
50053
50054
50055     // Connect the way to an existing way.
50056     drawWay.addWay = function(loc, edge) {
50057
50058         if (isArea) {
50059             context.perform(
50060                 actionAddMidpoint({ loc: loc, edge: edge}, end),
50061                 annotation
50062             );
50063         } else {
50064             var previousEdge = startIndex ?
50065                 [way.nodes[startIndex], way.nodes[startIndex - 1]] :
50066                 [way.nodes[0], way.nodes[1]];
50067
50068             // Avoid creating duplicate segments
50069             if (geoEdgeEqual(edge, previousEdge))
50070                 return;
50071
50072             var newNode = osmNode({ loc: loc });
50073             context.perform(
50074                 actionAddMidpoint({ loc: loc, edge: edge}, newNode),
50075                 ReplaceTemporaryNode(newNode),
50076                 annotation
50077             );
50078         }
50079
50080         finished = true;
50081         context.enter(mode);
50082     };
50083
50084
50085     // Connect the way to an existing node and continue drawing.
50086     drawWay.addNode = function(node) {
50087         // Avoid creating duplicate segments
50088         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
50089
50090         context.perform(
50091             ReplaceTemporaryNode(node),
50092             annotation
50093         );
50094
50095         finished = true;
50096         context.enter(mode);
50097     };
50098
50099
50100     // Finish the draw operation, removing the temporary node. If the way has enough
50101     // nodes to be valid, it's selected. Otherwise, return to browse mode.
50102     drawWay.finish = function() {
50103         context.pop();
50104         finished = true;
50105
50106         window.setTimeout(function() {
50107             context.map().dblclickEnable(true);
50108         }, 1000);
50109
50110         if (context.hasEntity(wayId)) {
50111             context.enter(
50112                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
50113             );
50114         } else {
50115             context.enter(modeBrowse(context));
50116         }
50117     };
50118
50119
50120     // Cancel the draw operation and return to browse, deleting everything drawn.
50121     drawWay.cancel = function() {
50122         context.perform(
50123             utilFunctor(baseGraph),
50124             t('operations.cancel_draw.annotation'));
50125
50126         window.setTimeout(function() {
50127             context.map().dblclickEnable(true);
50128         }, 1000);
50129
50130         finished = true;
50131         context.enter(modeBrowse(context));
50132     };
50133
50134
50135     drawWay.tail = function(text) {
50136         draw.tail(text);
50137         return drawWay;
50138     };
50139
50140
50141     return drawWay;
50142 }
50143
50144 function behaviorHash(context) {
50145     var s0 = null, // cached window.location.hash
50146         lat = 90 - 1e-8; // allowable latitude range
50147
50148
50149     var parser = function(map$$1, s) {
50150         var q = utilStringQs(s);
50151         var args = (q.map || '').split('/').map(Number);
50152         if (args.length < 3 || args.some(isNaN)) {
50153             return true; // replace bogus hash
50154         } else if (s !== formatter(map$$1).slice(1)) {
50155             map$$1.centerZoom([args[2],
50156                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
50157         }
50158     };
50159
50160
50161     var formatter = function(map$$1) {
50162         var mode = context.mode(),
50163             center = map$$1.center(),
50164             zoom$$1 = map$$1.zoom(),
50165             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
50166             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
50167             newParams = {};
50168
50169         if (mode && mode.id === 'browse') {
50170             delete q.id;
50171         } else {
50172             var selected = context.selectedIDs().filter(function(id) {
50173                 return !context.entity(id).isNew();
50174             });
50175             if (selected.length) {
50176                 newParams.id = selected.join(',');
50177             }
50178         }
50179
50180         newParams.map = zoom$$1.toFixed(2) +
50181                 '/' + center[1].toFixed(precision) +
50182                 '/' + center[0].toFixed(precision);
50183
50184         return '#' + utilQsString(lodash.assign(q, newParams), true);
50185     };
50186
50187
50188     function update() {
50189         if (context.inIntro()) return;
50190         var s1 = formatter(context.map());
50191         if (s0 !== s1) {
50192             window.location.replace(s0 = s1);  // don't recenter the map!
50193         }
50194     }
50195
50196
50197     var throttledUpdate = lodash.throttle(update, 500);
50198
50199
50200     function hashchange() {
50201         if (window.location.hash === s0) return;  // ignore spurious hashchange events
50202         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
50203             update(); // replace bogus hash
50204         }
50205     }
50206
50207
50208     function hash() {
50209         context.map()
50210             .on('move.hash', throttledUpdate);
50211
50212         context
50213             .on('enter.hash', throttledUpdate);
50214
50215         select(window)
50216             .on('hashchange.hash', hashchange);
50217
50218         if (window.location.hash) {
50219             var q = utilStringQs(window.location.hash.substring(1));
50220             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
50221             if (q.comment) context.storage('comment', q.comment);
50222             hashchange();
50223             if (q.map) hash.hadHash = true;
50224         }
50225     }
50226
50227
50228     hash.off = function() {
50229         throttledUpdate.cancel();
50230
50231         context.map()
50232             .on('move.hash', null);
50233
50234         context
50235             .on('enter.hash', null);
50236
50237         select(window)
50238             .on('hashchange.hash', null);
50239
50240         window.location.hash = '';
50241     };
50242
50243
50244     return hash;
50245 }
50246
50247 function behaviorLasso(context) {
50248
50249     var behavior = function(selection$$1) {
50250         var lasso;
50251
50252
50253         function mousedown() {
50254             var button = 0;  // left
50255             if (event.button === button && event.shiftKey === true) {
50256                 lasso = null;
50257
50258                 select(window)
50259                     .on('mousemove.lasso', mousemove)
50260                     .on('mouseup.lasso', mouseup);
50261
50262                 event.stopPropagation();
50263             }
50264         }
50265
50266
50267         function mousemove() {
50268             if (!lasso) {
50269                 lasso = uiLasso(context);
50270                 context.surface().call(lasso);
50271             }
50272
50273             lasso.p(context.mouse());
50274         }
50275
50276
50277         function normalize(a, b) {
50278             return [
50279                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
50280                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
50281         }
50282
50283
50284         function lassoed() {
50285             if (!lasso) return [];
50286
50287             var graph = context.graph(),
50288                 bounds = lasso.extent().map(context.projection.invert),
50289                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
50290
50291             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
50292                 return entity.type === 'node' &&
50293                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
50294                     !context.features().isHidden(entity, graph, entity.geometry(graph));
50295             }), 'id');
50296         }
50297
50298
50299         function mouseup() {
50300             select(window)
50301                 .on('mousemove.lasso', null)
50302                 .on('mouseup.lasso', null);
50303
50304             if (!lasso) return;
50305
50306             var ids = lassoed();
50307             lasso.close();
50308
50309             if (ids.length) {
50310                 context.enter(modeSelect(context, ids));
50311             }
50312         }
50313
50314         selection$$1
50315             .on('mousedown.lasso', mousedown);
50316     };
50317
50318
50319     behavior.off = function(selection$$1) {
50320         selection$$1.on('mousedown.lasso', null);
50321     };
50322
50323
50324     return behavior;
50325 }
50326
50327 /* Creates a keybinding behavior for an operation */
50328 function behaviorOperation(context) {
50329     var which, keybinding;
50330
50331
50332     var behavior = function () {
50333         if (which) {
50334             keybinding = d3keybinding('behavior.key.' + which.id);
50335             keybinding.on(which.keys, function() {
50336                 event.preventDefault();
50337                 if (which.available() && !which.disabled() && !context.inIntro()) {
50338                     which();
50339                 }
50340             });
50341             select(document).call(keybinding);
50342         }
50343         return behavior;
50344     };
50345
50346
50347     behavior.off = function() {
50348         if (keybinding) {
50349             select(document).call(keybinding.off);
50350         }
50351     };
50352
50353
50354     behavior.which = function (_) {
50355         if (!arguments.length) return which;
50356         which = _;
50357         return behavior;
50358     };
50359
50360
50361     return behavior;
50362 }
50363
50364 function behaviorPaste(context) {
50365     var keybinding = d3keybinding('paste');
50366
50367     function omitTag(v, k) {
50368         return (
50369             k === 'phone' ||
50370             k === 'fax' ||
50371             k === 'email' ||
50372             k === 'website' ||
50373             k === 'url' ||
50374             k === 'note' ||
50375             k === 'description' ||
50376             k.indexOf('name') !== -1 ||
50377             k.indexOf('wiki') === 0 ||
50378             k.indexOf('addr:') === 0 ||
50379             k.indexOf('contact:') === 0
50380         );
50381     }
50382
50383
50384     function doPaste() {
50385         event.preventDefault();
50386         if (context.inIntro()) return;
50387
50388         var baseGraph = context.graph(),
50389             mouse$$1 = context.mouse(),
50390             projection = context.projection,
50391             viewport = geoExtent$$1(projection.clipExtent()).polygon();
50392
50393         if (!geoPointInPolygon(mouse$$1, viewport)) return;
50394
50395         var extent$$1 = geoExtent$$1(),
50396             oldIDs = context.copyIDs(),
50397             oldGraph = context.copyGraph(),
50398             newIDs = [];
50399
50400         if (!oldIDs.length) return;
50401
50402         var action = actionCopyEntities(oldIDs, oldGraph);
50403         context.perform(action);
50404
50405         var copies = action.copies();
50406         var originals = lodash.invert(lodash.mapValues(copies, 'id'));
50407         for (var id in copies) {
50408             var oldEntity = oldGraph.entity(id),
50409                 newEntity = copies[id];
50410
50411             extent$$1._extend(oldEntity.extent(oldGraph));
50412             context.perform(
50413                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
50414             );
50415
50416             // Exclude child nodes from newIDs if their parent way was also copied.
50417             var parents = context.graph().parentWays(newEntity),
50418                 parentCopied = false;
50419             for (var i = 0; i < parents.length; i++) {
50420                 if (originals[parents[i].id]) {
50421                     parentCopied = true;
50422                     break;
50423                 }
50424             }
50425
50426             if (!parentCopied) {
50427                 newIDs.push(newEntity.id);
50428             }
50429         }
50430
50431         // Put pasted objects where mouse pointer is..
50432         var center = projection(extent$$1.center()),
50433             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
50434
50435         context.perform(actionMove(newIDs, delta, projection));
50436         context.enter(modeMove$$1(context, newIDs, baseGraph));
50437     }
50438
50439
50440     function paste() {
50441         keybinding.on(uiCmd('⌘V'), doPaste);
50442         select(document).call(keybinding);
50443         return paste;
50444     }
50445
50446
50447     paste.off = function() {
50448         select(document).call(keybinding.off);
50449     };
50450
50451
50452     return paste;
50453 }
50454
50455 function behaviorSelect(context) {
50456
50457     function keydown() {
50458         if (event && event.shiftKey) {
50459             context.surface()
50460                 .classed('behavior-multiselect', true);
50461         }
50462     }
50463
50464
50465     function keyup() {
50466         if (!event || !event.shiftKey) {
50467             context.surface()
50468                 .classed('behavior-multiselect', false);
50469         }
50470     }
50471
50472
50473     function click() {
50474         var datum = event.target.__data__,
50475             lasso = select('#surface .lasso').node(),
50476             mode = context.mode();
50477
50478         if (datum.type === 'midpoint') {
50479             // do nothing
50480         } else if (!(datum instanceof osmEntity$$1)) {
50481             if (!event.shiftKey && !lasso && mode.id !== 'browse')
50482                 context.enter(modeBrowse(context));
50483
50484         } else if (!event.shiftKey && !lasso) {
50485             // Avoid re-entering Select mode with same entity.
50486             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
50487                 context.enter(modeSelect(context, [datum.id]));
50488             } else {
50489                 mode.suppressMenu(false).reselect();
50490             }
50491         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
50492             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
50493             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
50494
50495         } else {
50496             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
50497         }
50498     }
50499
50500
50501     var behavior = function(selection$$1) {
50502         select(window)
50503             .on('keydown.select', keydown)
50504             .on('keyup.select', keyup);
50505
50506         selection$$1.on('click.select', click);
50507
50508         keydown();
50509     };
50510
50511
50512     behavior.off = function(selection$$1) {
50513         select(window)
50514             .on('keydown.select', null)
50515             .on('keyup.select', null);
50516
50517         selection$$1.on('click.select', null);
50518
50519         keyup();
50520     };
50521
50522
50523     return behavior;
50524 }
50525
50526 function modeAddArea$$1(context) {
50527     var mode = {
50528         id: 'add-area',
50529         button: 'area',
50530         title: t('modes.add_area.title'),
50531         description: t('modes.add_area.description'),
50532         key: '3'
50533     };
50534
50535     var behavior = behaviorAddWay(context)
50536             .tail(t('modes.add_area.tail'))
50537             .on('start', start)
50538             .on('startFromWay', startFromWay)
50539             .on('startFromNode', startFromNode),
50540         defaultTags = { area: 'yes' };
50541
50542
50543     function actionClose(wayId) {
50544         return function (graph) {
50545             return graph.replace(graph.entity(wayId).close());
50546         };
50547     }
50548
50549
50550     function start(loc) {
50551         var graph = context.graph(),
50552             node = osmNode({ loc: loc }),
50553             way = osmWay({ tags: defaultTags });
50554
50555         context.perform(
50556             actionAddEntity(node),
50557             actionAddEntity(way),
50558             actionAddVertex(way.id, node.id),
50559             actionClose(way.id)
50560         );
50561
50562         context.enter(modeDrawArea(context, way.id, graph));
50563     }
50564
50565
50566     function startFromWay(loc, edge) {
50567         var graph = context.graph(),
50568             node = osmNode({ loc: loc }),
50569             way = osmWay({ tags: defaultTags });
50570
50571         context.perform(
50572             actionAddEntity(node),
50573             actionAddEntity(way),
50574             actionAddVertex(way.id, node.id),
50575             actionClose(way.id),
50576             actionAddMidpoint({ loc: loc, edge: edge }, node)
50577         );
50578
50579         context.enter(modeDrawArea(context, way.id, graph));
50580     }
50581
50582
50583     function startFromNode(node) {
50584         var graph = context.graph(),
50585             way = osmWay({ tags: defaultTags });
50586
50587         context.perform(
50588             actionAddEntity(way),
50589             actionAddVertex(way.id, node.id),
50590             actionClose(way.id)
50591         );
50592
50593         context.enter(modeDrawArea(context, way.id, graph));
50594     }
50595
50596
50597     mode.enter = function() {
50598         context.install(behavior);
50599     };
50600
50601
50602     mode.exit = function() {
50603         context.uninstall(behavior);
50604     };
50605
50606
50607     return mode;
50608 }
50609
50610 function modeAddLine$$1(context) {
50611     var mode = {
50612         id: 'add-line',
50613         button: 'line',
50614         title: t('modes.add_line.title'),
50615         description: t('modes.add_line.description'),
50616         key: '2'
50617     };
50618
50619     var behavior = behaviorAddWay(context)
50620         .tail(t('modes.add_line.tail'))
50621         .on('start', start)
50622         .on('startFromWay', startFromWay)
50623         .on('startFromNode', startFromNode);
50624
50625
50626     function start(loc) {
50627         var baseGraph = context.graph(),
50628             node = osmNode({ loc: loc }),
50629             way = osmWay();
50630
50631         context.perform(
50632             actionAddEntity(node),
50633             actionAddEntity(way),
50634             actionAddVertex(way.id, node.id)
50635         );
50636
50637         context.enter(modeDrawLine(context, way.id, baseGraph));
50638     }
50639
50640
50641     function startFromWay(loc, edge) {
50642         var baseGraph = context.graph(),
50643             node = osmNode({ loc: loc }),
50644             way = osmWay();
50645
50646         context.perform(
50647             actionAddEntity(node),
50648             actionAddEntity(way),
50649             actionAddVertex(way.id, node.id),
50650             actionAddMidpoint({ loc: loc, edge: edge }, node)
50651         );
50652
50653         context.enter(modeDrawLine(context, way.id, baseGraph));
50654     }
50655
50656
50657     function startFromNode(node) {
50658         var baseGraph = context.graph(),
50659             way = osmWay();
50660
50661         context.perform(
50662             actionAddEntity(way),
50663             actionAddVertex(way.id, node.id)
50664         );
50665
50666         context.enter(modeDrawLine(context, way.id, baseGraph));
50667     }
50668
50669
50670     mode.enter = function() {
50671         context.install(behavior);
50672     };
50673
50674
50675     mode.exit = function() {
50676         context.uninstall(behavior);
50677     };
50678
50679     return mode;
50680 }
50681
50682 function modeAddPoint$$1(context) {
50683     var mode = {
50684         id: 'add-point',
50685         button: 'point',
50686         title: t('modes.add_point.title'),
50687         description: t('modes.add_point.description'),
50688         key: '1'
50689     };
50690
50691     var behavior = behaviorDraw(context)
50692         .tail(t('modes.add_point.tail'))
50693         .on('click', add)
50694         .on('clickWay', addWay)
50695         .on('clickNode', addNode)
50696         .on('cancel', cancel)
50697         .on('finish', cancel);
50698
50699
50700     function add(loc) {
50701         var node = osmNode({ loc: loc });
50702
50703         context.perform(
50704             actionAddEntity(node),
50705             t('operations.add.annotation.point')
50706         );
50707
50708         context.enter(
50709             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50710         );
50711     }
50712
50713
50714     function addWay(loc) {
50715         add(loc);
50716     }
50717
50718
50719     function addNode(node) {
50720         add(node.loc);
50721     }
50722
50723
50724     function cancel() {
50725         context.enter(modeBrowse(context));
50726     }
50727
50728
50729     mode.enter = function() {
50730         context.install(behavior);
50731     };
50732
50733
50734     mode.exit = function() {
50735         context.uninstall(behavior);
50736     };
50737
50738
50739     return mode;
50740 }
50741
50742 function modeBrowse(context) {
50743     var mode = {
50744         button: 'browse',
50745         id: 'browse',
50746         title: t('modes.browse.title'),
50747         description: t('modes.browse.description')
50748     }, sidebar;
50749
50750     var behaviors = [
50751         behaviorPaste(context),
50752         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50753         behaviorSelect(context),
50754         behaviorLasso(context)
50755     ];
50756
50757
50758     mode.enter = function() {
50759         behaviors.forEach(function(behavior) {
50760             context.install(behavior);
50761         });
50762
50763         // Get focus on the body.
50764         if (document.activeElement && document.activeElement.blur) {
50765             document.activeElement.blur();
50766         }
50767
50768         if (sidebar) {
50769             context.ui().sidebar.show(sidebar);
50770         } else {
50771             context.ui().sidebar.select(null);
50772         }
50773     };
50774
50775
50776     mode.exit = function() {
50777         context.ui().sidebar.hover.cancel();
50778         behaviors.forEach(function(behavior) {
50779             context.uninstall(behavior);
50780         });
50781
50782         if (sidebar) {
50783             context.ui().sidebar.hide();
50784         }
50785     };
50786
50787
50788     mode.sidebar = function(_) {
50789         if (!arguments.length) return sidebar;
50790         sidebar = _;
50791         return mode;
50792     };
50793
50794
50795     return mode;
50796 }
50797
50798 function modeDragNode$$1(context) {
50799     var mode = {
50800         id: 'drag-node',
50801         button: 'browse'
50802     };
50803
50804     var nudgeInterval,
50805         activeIDs,
50806         wasMidpoint,
50807         isCancelled,
50808         lastLoc,
50809         selectedIDs = [],
50810         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50811         edit = behaviorEdit(context);
50812
50813
50814     function vecSub(a, b) {
50815         return [a[0] - b[0], a[1] - b[1]];
50816     }
50817
50818     function edge(point, size) {
50819         var pad = [30, 100, 30, 100],
50820             x = 0,
50821             y = 0;
50822
50823         if (point[0] > size[0] - pad[0])
50824             x = -10;
50825         if (point[0] < pad[2])
50826             x = 10;
50827         if (point[1] > size[1] - pad[1])
50828             y = -10;
50829         if (point[1] < pad[3])
50830             y = 10;
50831
50832         if (x || y) {
50833             return [x, y];
50834         } else {
50835             return null;
50836         }
50837     }
50838
50839
50840     function startNudge(entity, nudge) {
50841         if (nudgeInterval) window.clearInterval(nudgeInterval);
50842         nudgeInterval = window.setInterval(function() {
50843             context.pan(nudge);
50844             doMove(entity, nudge);
50845         }, 50);
50846     }
50847
50848
50849     function stopNudge() {
50850         if (nudgeInterval) window.clearInterval(nudgeInterval);
50851         nudgeInterval = null;
50852     }
50853
50854
50855     function moveAnnotation(entity) {
50856         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50857     }
50858
50859
50860     function connectAnnotation(entity) {
50861         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50862     }
50863
50864
50865     function origin(entity) {
50866         return context.projection(entity.loc);
50867     }
50868
50869
50870     function start(entity) {
50871         wasMidpoint = entity.type === 'midpoint';
50872
50873         // vertices classed "sibling" include:  (see svg/vertices.js)
50874         // - children of selected ways or multipolygons
50875         // - vertices sharing a way with selected vertices
50876         var selection$$1 = selectAll('g.' + entity.id),
50877             isSelected = !selection$$1.empty() &&
50878                 (selection$$1.classed('selected') || selection$$1.classed('sibling'));
50879
50880         isCancelled = event.sourceEvent.shiftKey || !(wasMidpoint || isSelected) ||
50881             context.features().hasHiddenConnections(entity, context.graph());
50882
50883         if (isCancelled) {
50884             return behavior.cancel();
50885         }
50886
50887         if (wasMidpoint) {
50888             var midpoint = entity;
50889             entity = osmNode();
50890             context.perform(actionAddMidpoint(midpoint, entity));
50891
50892             var vertex = context.surface().selectAll('.' + entity.id);
50893             behavior.target(vertex.node(), entity);
50894
50895         } else {
50896             context.perform(actionNoop());
50897         }
50898
50899         // activeIDs generate no pointer events.  This prevents the node or vertex
50900         // being dragged from trying to connect to itself or its parent element.
50901         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50902         activeIDs.push(entity.id);
50903         setActiveElements();
50904
50905         context.enter(mode);
50906     }
50907
50908
50909     function datum() {
50910         var event$$1 = event && event.sourceEvent;
50911         if (!event$$1 || event$$1.altKey) {
50912             return {};
50913         } else {
50914             return event$$1.target.__data__ || {};
50915         }
50916     }
50917
50918
50919     function doMove(entity, nudge) {
50920         nudge = nudge || [0, 0];
50921
50922         var currPoint = (event && event.point) || context.projection(lastLoc),
50923             currMouse = vecSub(currPoint, nudge),
50924             loc = context.projection.invert(currMouse),
50925             d = datum();
50926
50927         if (d.type === 'node' && d.id !== entity.id) {
50928             loc = d.loc;
50929         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50930             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50931         }
50932
50933         context.replace(
50934             actionMoveNode(entity.id, loc),
50935             moveAnnotation(entity)
50936         );
50937
50938         lastLoc = loc;
50939     }
50940
50941
50942     function move(entity) {
50943         if (isCancelled) return;
50944         event.sourceEvent.stopPropagation();
50945         lastLoc = context.projection.invert(event.point);
50946
50947         doMove(entity);
50948         var nudge = edge(event.point, context.map().dimensions());
50949         if (nudge) startNudge(entity, nudge);
50950         else stopNudge();
50951     }
50952
50953
50954     function end(entity) {
50955         if (isCancelled) return;
50956
50957         var d = datum();
50958
50959         if (d.type === 'way') {
50960             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
50961             context.replace(
50962                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
50963                 connectAnnotation(d)
50964             );
50965
50966         } else if (d.type === 'node' && d.id !== entity.id) {
50967             context.replace(
50968                 actionConnect([d.id, entity.id]),
50969                 connectAnnotation(d)
50970             );
50971
50972         } else if (wasMidpoint) {
50973             context.replace(
50974                 actionNoop(),
50975                 t('operations.add.annotation.vertex')
50976             );
50977
50978         } else {
50979             context.replace(
50980                 actionNoop(),
50981                 moveAnnotation(entity)
50982             );
50983         }
50984
50985         var reselection = selectedIDs.filter(function(id) {
50986             return context.graph().hasEntity(id);
50987         });
50988
50989         if (reselection.length) {
50990             context.enter(modeSelect(context, reselection).suppressMenu(true));
50991         } else {
50992             context.enter(modeBrowse(context));
50993         }
50994     }
50995
50996
50997     function cancel() {
50998         behavior.cancel();
50999         context.enter(modeBrowse(context));
51000     }
51001
51002
51003     function setActiveElements() {
51004         context.surface().selectAll(utilEntitySelector(activeIDs))
51005             .classed('active', true);
51006     }
51007
51008
51009     var behavior = behaviorDrag()
51010         .delegate('g.node, g.point, g.midpoint')
51011         .surface(select('#map').node())
51012         .origin(origin)
51013         .on('start', start)
51014         .on('move', move)
51015         .on('end', end);
51016
51017
51018     mode.enter = function() {
51019         context.install(hover);
51020         context.install(edit);
51021
51022         context.history()
51023             .on('undone.drag-node', cancel);
51024
51025         context.map()
51026             .on('drawn.drag-node', setActiveElements);
51027
51028         setActiveElements();
51029     };
51030
51031
51032     mode.exit = function() {
51033         context.ui().sidebar.hover.cancel();
51034         context.uninstall(hover);
51035         context.uninstall(edit);
51036
51037         context.history()
51038             .on('undone.drag-node', null);
51039
51040         context.map()
51041             .on('drawn.drag-node', null);
51042
51043         context.surface()
51044             .selectAll('.active')
51045             .classed('active', false);
51046
51047         stopNudge();
51048     };
51049
51050
51051     mode.selectedIDs = function(_) {
51052         if (!arguments.length) return selectedIDs;
51053         selectedIDs = _;
51054         return mode;
51055     };
51056
51057
51058     mode.behavior = behavior;
51059
51060
51061     return mode;
51062 }
51063
51064 function modeDrawArea(context, wayId, baseGraph) {
51065     var mode = {
51066         button: 'area',
51067         id: 'draw-area'
51068     };
51069
51070     var behavior;
51071
51072
51073     mode.enter = function() {
51074         var way = context.entity(wayId);
51075
51076         behavior = behaviorDrawWay(context, wayId, undefined, mode, baseGraph)
51077             .tail(t('modes.draw_area.tail'));
51078
51079         var addNode = behavior.addNode;
51080
51081         behavior.addNode = function(node) {
51082             var length = way.nodes.length,
51083                 penultimate = length > 2 ? way.nodes[length - 2] : null;
51084
51085             if (node.id === way.first() || node.id === penultimate) {
51086                 behavior.finish();
51087             } else {
51088                 addNode(node);
51089             }
51090         };
51091
51092         context.install(behavior);
51093     };
51094
51095
51096     mode.exit = function() {
51097         context.uninstall(behavior);
51098     };
51099
51100
51101     mode.selectedIDs = function() {
51102         return [wayId];
51103     };
51104
51105
51106     return mode;
51107 }
51108
51109 function modeDrawLine(context, wayId, baseGraph, affix) {
51110     var mode = {
51111         button: 'line',
51112         id: 'draw-line'
51113     };
51114
51115     var behavior;
51116
51117
51118     mode.enter = function() {
51119         var way = context.entity(wayId),
51120             index = (affix === 'prefix') ? 0 : undefined,
51121             headId = (affix === 'prefix') ? way.first() : way.last();
51122
51123         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
51124             .tail(t('modes.draw_line.tail'));
51125
51126         var addNode = behavior.addNode;
51127
51128         behavior.addNode = function(node) {
51129             if (node.id === headId) {
51130                 behavior.finish();
51131             } else {
51132                 addNode(node);
51133             }
51134         };
51135
51136         context.install(behavior);
51137     };
51138
51139
51140     mode.exit = function() {
51141         context.uninstall(behavior);
51142     };
51143
51144
51145     mode.selectedIDs = function() {
51146         return [wayId];
51147     };
51148
51149
51150     return mode;
51151 }
51152
51153 function operationCircularize(selectedIDs, context) {
51154     var entityId = selectedIDs[0],
51155         entity = context.entity(entityId),
51156         extent = entity.extent(context.graph()),
51157         geometry = context.geometry(entityId),
51158         action = actionCircularize(entityId, context.projection);
51159
51160
51161     var operation = function() {
51162         context.perform(action, t('operations.circularize.annotation.' + geometry));
51163     };
51164
51165
51166     operation.available = function() {
51167         return selectedIDs.length === 1 &&
51168             entity.type === 'way' &&
51169             lodash.uniq(entity.nodes).length > 1;
51170     };
51171
51172
51173     operation.disabled = function() {
51174         var reason;
51175         if (extent.percentContainedIn(context.extent()) < 0.8) {
51176             reason = 'too_large';
51177         } else if (context.hasHiddenConnections(entityId)) {
51178             reason = 'connected_to_hidden';
51179         }
51180         return action.disabled(context.graph()) || reason;
51181     };
51182
51183
51184     operation.tooltip = function() {
51185         var disable = operation.disabled();
51186         return disable ?
51187             t('operations.circularize.' + disable) :
51188             t('operations.circularize.description.' + geometry);
51189     };
51190
51191
51192     operation.id = 'circularize';
51193     operation.keys = [t('operations.circularize.key')];
51194     operation.title = t('operations.circularize.title');
51195     operation.behavior = behaviorOperation(context).which(operation);
51196
51197     return operation;
51198 }
51199
51200 function operationContinue(selectedIDs, context) {
51201     var graph = context.graph(),
51202         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51203         geometries = lodash.extend({ line: [], vertex: [] },
51204             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51205         vertex = geometries.vertex[0];
51206
51207
51208     function candidateWays() {
51209         return graph.parentWays(vertex).filter(function(parent) {
51210             return parent.geometry(graph) === 'line' &&
51211                 !parent.isClosed() &&
51212                 parent.affix(vertex.id) &&
51213                 (geometries.line.length === 0 || geometries.line[0] === parent);
51214         });
51215     }
51216
51217
51218     var operation = function() {
51219         var candidate = candidateWays()[0];
51220         context.enter(
51221             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51222         );
51223     };
51224
51225
51226     operation.available = function() {
51227         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51228             !context.features().hasHiddenConnections(vertex, context.graph());
51229     };
51230
51231
51232     operation.disabled = function() {
51233         var candidates = candidateWays();
51234         if (candidates.length === 0)
51235             return 'not_eligible';
51236         if (candidates.length > 1)
51237             return 'multiple';
51238     };
51239
51240
51241     operation.tooltip = function() {
51242         var disable = operation.disabled();
51243         return disable ?
51244             t('operations.continue.' + disable) :
51245             t('operations.continue.description');
51246     };
51247
51248
51249     operation.id = 'continue';
51250     operation.keys = [t('operations.continue.key')];
51251     operation.title = t('operations.continue.title');
51252     operation.behavior = behaviorOperation(context).which(operation);
51253
51254     return operation;
51255 }
51256
51257 function operationDelete(selectedIDs, context) {
51258     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51259         action = actionDeleteMultiple(selectedIDs);
51260
51261
51262     var operation = function() {
51263         var annotation,
51264             nextSelectedID;
51265
51266         if (selectedIDs.length > 1) {
51267             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51268
51269         } else {
51270             var id = selectedIDs[0],
51271                 entity = context.entity(id),
51272                 geometry = context.geometry(id),
51273                 parents = context.graph().parentWays(entity),
51274                 parent = parents[0];
51275
51276             annotation = t('operations.delete.annotation.' + geometry);
51277
51278             // Select the next closest node in the way.
51279             if (geometry === 'vertex' && parent.nodes.length > 2) {
51280                 var nodes = parent.nodes,
51281                     i = nodes.indexOf(id);
51282
51283                 if (i === 0) {
51284                     i++;
51285                 } else if (i === nodes.length - 1) {
51286                     i--;
51287                 } else {
51288                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51289                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51290                     i = a < b ? i - 1 : i + 1;
51291                 }
51292
51293                 nextSelectedID = nodes[i];
51294             }
51295         }
51296
51297         context.perform(action, annotation);
51298
51299         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51300             context.enter(
51301                 modeSelect(context, [nextSelectedID]).follow(true).suppressMenu(true)
51302             );
51303         } else {
51304             context.enter(modeBrowse(context));
51305         }
51306
51307     };
51308
51309
51310     operation.available = function() {
51311         return true;
51312     };
51313
51314
51315     operation.disabled = function() {
51316         var reason;
51317         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51318             reason = 'connected_to_hidden';
51319         } else if (lodash.some(selectedIDs, protectedMember)) {
51320             reason = 'part_of_relation';
51321         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51322             reason = 'incomplete_relation';
51323         }
51324         return reason;
51325
51326         function incompleteRelation(id) {
51327             var entity = context.entity(id);
51328             return entity.type === 'relation' && !entity.isComplete(context.graph());
51329         }
51330
51331         function protectedMember(id) {
51332             var entity = context.entity(id);
51333             if (entity.type !== 'way') return false;
51334
51335             var parents = context.graph().parentRelations(entity);
51336             for (var i = 0; i < parents.length; i++) {
51337                 var parent = parents[i],
51338                     type = parent.tags.type,
51339                     role = parent.memberById(id).role || 'outer';
51340                 if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
51341                     return true;
51342                 }
51343             }
51344             return false;
51345         }
51346
51347     };
51348
51349
51350     operation.tooltip = function() {
51351         var disable = operation.disabled();
51352         return disable ?
51353             t('operations.delete.' + disable + '.' + multi) :
51354             t('operations.delete.description' + '.' + multi);
51355     };
51356
51357
51358     operation.id = 'delete';
51359     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51360     operation.title = t('operations.delete.title');
51361     operation.behavior = behaviorOperation(context).which(operation);
51362
51363     return operation;
51364 }
51365
51366 function operationDisconnect(selectedIDs, context) {
51367     var vertices = lodash.filter(selectedIDs, function(entityId) {
51368         return context.geometry(entityId) === 'vertex';
51369     });
51370
51371     var entityId = vertices[0],
51372         action = actionDisconnect(entityId);
51373
51374     if (selectedIDs.length > 1) {
51375         action.limitWays(lodash.without(selectedIDs, entityId));
51376     }
51377
51378
51379     var operation = function() {
51380         context.perform(action, t('operations.disconnect.annotation'));
51381     };
51382
51383
51384     operation.available = function() {
51385         return vertices.length === 1;
51386     };
51387
51388
51389     operation.disabled = function() {
51390         var reason;
51391         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51392             reason = 'connected_to_hidden';
51393         }
51394         return action.disabled(context.graph()) || reason;
51395     };
51396
51397
51398     operation.tooltip = function() {
51399         var disable = operation.disabled();
51400         return disable ?
51401             t('operations.disconnect.' + disable) :
51402             t('operations.disconnect.description');
51403     };
51404
51405
51406     operation.id = 'disconnect';
51407     operation.keys = [t('operations.disconnect.key')];
51408     operation.title = t('operations.disconnect.title');
51409     operation.behavior = behaviorOperation(context).which(operation);
51410
51411     return operation;
51412 }
51413
51414 function operationMerge(selectedIDs, context) {
51415     var join = actionJoin(selectedIDs),
51416         merge = actionMerge(selectedIDs),
51417         mergePolygon = actionMergePolygon(selectedIDs);
51418
51419     var operation = function() {
51420         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51421             action;
51422
51423         if (!join.disabled(context.graph())) {
51424             action = join;
51425         } else if (!merge.disabled(context.graph())) {
51426             action = merge;
51427         } else {
51428             action = mergePolygon;
51429         }
51430
51431         context.perform(action, annotation);
51432         var ids = selectedIDs.filter(function(id) {
51433             var entity = context.hasEntity(id);
51434             return entity && entity.type !== 'node';
51435         });
51436         context.enter(modeSelect(context, ids).suppressMenu(true));
51437     };
51438
51439
51440     operation.available = function() {
51441         return selectedIDs.length >= 2;
51442     };
51443
51444
51445     operation.disabled = function() {
51446         return join.disabled(context.graph()) &&
51447             merge.disabled(context.graph()) &&
51448             mergePolygon.disabled(context.graph());
51449     };
51450
51451
51452     operation.tooltip = function() {
51453         var j = join.disabled(context.graph()),
51454             m = merge.disabled(context.graph()),
51455             p = mergePolygon.disabled(context.graph());
51456
51457         if (j === 'restriction' && m && p) {
51458             return t('operations.merge.restriction',
51459                 { relation: context.presets().item('type/restriction').name() });
51460         }
51461
51462         if (p === 'incomplete_relation' && j && m) {
51463             return t('operations.merge.incomplete_relation');
51464         }
51465
51466         if (j && m && p) {
51467             return t('operations.merge.' + j);
51468         }
51469
51470         return t('operations.merge.description');
51471     };
51472
51473
51474     operation.id = 'merge';
51475     operation.keys = [t('operations.merge.key')];
51476     operation.title = t('operations.merge.title');
51477     operation.behavior = behaviorOperation(context).which(operation);
51478
51479     return operation;
51480 }
51481
51482 function operationMove(selectedIDs, context) {
51483     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51484         extent = selectedIDs.reduce(function(extent, id) {
51485             return extent.extend(context.entity(id).extent(context.graph()));
51486         }, geoExtent$$1());
51487
51488
51489     var operation = function() {
51490         context.enter(modeMove$$1(context, selectedIDs));
51491     };
51492
51493
51494     operation.available = function() {
51495         return selectedIDs.length > 1 ||
51496             context.entity(selectedIDs[0]).type !== 'node';
51497     };
51498
51499
51500     operation.disabled = function() {
51501         var reason;
51502         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51503             reason = 'too_large';
51504         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51505             reason = 'connected_to_hidden';
51506         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51507             reason = 'incomplete_relation';
51508         }
51509         return reason;
51510
51511         function incompleteRelation(id) {
51512             var entity = context.entity(id);
51513             return entity.type === 'relation' && !entity.isComplete(context.graph());
51514         }
51515     };
51516
51517
51518     operation.tooltip = function() {
51519         var disable = operation.disabled();
51520         return disable ?
51521             t('operations.move.' + disable + '.' + multi) :
51522             t('operations.move.description.' + multi);
51523     };
51524
51525
51526     operation.id = 'move';
51527     operation.keys = [t('operations.move.key')];
51528     operation.title = t('operations.move.title');
51529     operation.behavior = behaviorOperation(context).which(operation);
51530
51531     return operation;
51532 }
51533
51534 function operationOrthogonalize(selectedIDs, context) {
51535     var entityId = selectedIDs[0],
51536         entity = context.entity(entityId),
51537         extent = entity.extent(context.graph()),
51538         geometry = context.geometry(entityId),
51539         action = actionOrthogonalize(entityId, context.projection);
51540
51541
51542     var operation = function() {
51543         context.perform(action, t('operations.orthogonalize.annotation.' + geometry));
51544     };
51545
51546
51547     operation.available = function() {
51548         return selectedIDs.length === 1 &&
51549             entity.type === 'way' &&
51550             entity.isClosed() &&
51551             lodash.uniq(entity.nodes).length > 2;
51552     };
51553
51554
51555     operation.disabled = function() {
51556         var reason;
51557         if (extent.percentContainedIn(context.extent()) < 0.8) {
51558             reason = 'too_large';
51559         } else if (context.hasHiddenConnections(entityId)) {
51560             reason = 'connected_to_hidden';
51561         }
51562         return action.disabled(context.graph()) || reason;
51563     };
51564
51565
51566     operation.tooltip = function() {
51567         var disable = operation.disabled();
51568         return disable ?
51569             t('operations.orthogonalize.' + disable) :
51570             t('operations.orthogonalize.description.' + geometry);
51571     };
51572
51573
51574     operation.id = 'orthogonalize';
51575     operation.keys = [t('operations.orthogonalize.key')];
51576     operation.title = t('operations.orthogonalize.title');
51577     operation.behavior = behaviorOperation(context).which(operation);
51578
51579     return operation;
51580 }
51581
51582 function operationReflectShort(selectedIDs, context) {
51583     return operationReflect(selectedIDs, context, 'short');
51584 }
51585
51586
51587 function operationReflectLong(selectedIDs, context) {
51588     return operationReflect(selectedIDs, context, 'long');
51589 }
51590
51591
51592 function operationReflect(selectedIDs, context, axis) {
51593     axis = axis || 'long';
51594     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51595         extent = selectedIDs.reduce(function(extent, id) {
51596             return extent.extend(context.entity(id).extent(context.graph()));
51597         }, geoExtent$$1());
51598
51599
51600     var operation = function() {
51601         var action = actionReflect(selectedIDs, context.projection)
51602             .useLongAxis(Boolean(axis === 'long'));
51603         context.perform(action, t('operations.reflect.annotation.' + axis + '.' + multi));
51604     };
51605
51606
51607     operation.available = function() {
51608         return lodash.some(selectedIDs, hasArea);
51609
51610         function hasArea(id) {
51611             var entity = context.entity(id);
51612             return (entity.type === 'way' && entity.isClosed()) ||
51613                 (entity.type ==='relation' && entity.isMultipolygon());
51614         }
51615     };
51616
51617
51618     operation.disabled = function() {
51619         var reason;
51620         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51621             reason = 'too_large';
51622         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51623             reason = 'connected_to_hidden';
51624         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51625             reason = 'incomplete_relation';
51626         }
51627         return reason;
51628
51629         function incompleteRelation(id) {
51630             var entity = context.entity(id);
51631             return entity.type === 'relation' && !entity.isComplete(context.graph());
51632         }
51633     };
51634
51635
51636     operation.tooltip = function() {
51637         var disable = operation.disabled();
51638         return disable ?
51639             t('operations.reflect.' + disable + '.' + multi) :
51640             t('operations.reflect.description.' + axis + '.' + multi);
51641     };
51642
51643
51644     operation.id = 'reflect-' + axis;
51645     operation.keys = [t('operations.reflect.key.' + axis)];
51646     operation.title = t('operations.reflect.title');
51647     operation.behavior = behaviorOperation(context).which(operation);
51648
51649     return operation;
51650 }
51651
51652 function operationReverse(selectedIDs, context) {
51653     var entityId = selectedIDs[0];
51654
51655     var operation = function() {
51656         context.perform(actionReverse(entityId), t('operations.reverse.annotation'));
51657     };
51658
51659
51660     operation.available = function() {
51661         return selectedIDs.length === 1 && context.geometry(entityId) === 'line';
51662     };
51663
51664
51665     operation.disabled = function() {
51666         return false;
51667     };
51668
51669
51670     operation.tooltip = function() {
51671         return t('operations.reverse.description');
51672     };
51673
51674
51675     operation.id = 'reverse';
51676     operation.keys = [t('operations.reverse.key')];
51677     operation.title = t('operations.reverse.title');
51678     operation.behavior = behaviorOperation(context).which(operation);
51679
51680     return operation;
51681 }
51682
51683 function operationRotate(selectedIDs, context) {
51684     var multi = (selectedIDs.length === 1 ? 'single' : 'multiple'),
51685         extent = selectedIDs.reduce(function(extent, id) {
51686             return extent.extend(context.entity(id).extent(context.graph()));
51687         }, geoExtent$$1());
51688
51689
51690     var operation = function() {
51691         context.enter(modeRotate$$1(context, selectedIDs));
51692     };
51693
51694
51695     operation.available = function() {
51696         return lodash.some(selectedIDs, hasArea);
51697
51698         function hasArea(id) {
51699             var entity = context.entity(id);
51700             return (entity.type === 'way' && entity.isClosed()) ||
51701                 (entity.type ==='relation' && entity.isMultipolygon());
51702         }
51703     };
51704
51705
51706     operation.disabled = function() {
51707         var reason;
51708         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51709             reason = 'too_large';
51710         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51711             reason = 'connected_to_hidden';
51712         } else if (lodash.some(selectedIDs, incompleteRelation)) {
51713             reason = 'incomplete_relation';
51714         }
51715         return reason;
51716
51717         function incompleteRelation(id) {
51718             var entity = context.entity(id);
51719             return entity.type === 'relation' && !entity.isComplete(context.graph());
51720         }
51721     };
51722
51723
51724     operation.tooltip = function() {
51725         var disable = operation.disabled();
51726         return disable ?
51727             t('operations.rotate.' + disable + '.' + multi) :
51728             t('operations.rotate.description.' + multi);
51729     };
51730
51731
51732     operation.id = 'rotate';
51733     operation.keys = [t('operations.rotate.key')];
51734     operation.title = t('operations.rotate.title');
51735     operation.behavior = behaviorOperation(context).which(operation);
51736
51737     return operation;
51738 }
51739
51740 function operationSplit(selectedIDs, context) {
51741     var vertices = lodash.filter(selectedIDs, function(entityId) {
51742         return context.geometry(entityId) === 'vertex';
51743     });
51744
51745     var entityId = vertices[0],
51746         action = actionSplit(entityId);
51747
51748     if (selectedIDs.length > 1) {
51749         action.limitWays(lodash.without(selectedIDs, entityId));
51750     }
51751
51752
51753     var operation = function() {
51754         var annotation;
51755
51756         var ways = action.ways(context.graph());
51757         if (ways.length === 1) {
51758             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51759         } else {
51760             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51761         }
51762
51763         var difference = context.perform(action, annotation);
51764         context.enter(modeSelect(context, difference.extantIDs()));
51765     };
51766
51767
51768     operation.available = function() {
51769         return vertices.length === 1;
51770     };
51771
51772
51773     operation.disabled = function() {
51774         var reason;
51775         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51776             reason = 'connected_to_hidden';
51777         }
51778         return action.disabled(context.graph()) || reason;
51779     };
51780
51781
51782     operation.tooltip = function() {
51783         var disable = operation.disabled();
51784         if (disable) {
51785             return t('operations.split.' + disable);
51786         }
51787
51788         var ways = action.ways(context.graph());
51789         if (ways.length === 1) {
51790             return t('operations.split.description.' + context.geometry(ways[0].id));
51791         } else {
51792             return t('operations.split.description.multiple');
51793         }
51794     };
51795
51796
51797     operation.id = 'split';
51798     operation.keys = [t('operations.split.key')];
51799     operation.title = t('operations.split.title');
51800     operation.behavior = behaviorOperation(context).which(operation);
51801
51802     return operation;
51803 }
51804
51805 function operationStraighten(selectedIDs, context) {
51806     var entityId = selectedIDs[0],
51807         action = actionStraighten(entityId, context.projection);
51808
51809
51810     function operation() {
51811         context.perform(action, t('operations.straighten.annotation'));
51812     }
51813
51814
51815     operation.available = function() {
51816         var entity = context.entity(entityId);
51817         return selectedIDs.length === 1 &&
51818             entity.type === 'way' &&
51819             !entity.isClosed() &&
51820             lodash.uniq(entity.nodes).length > 2;
51821     };
51822
51823
51824     operation.disabled = function() {
51825         var reason;
51826         if (context.hasHiddenConnections(entityId)) {
51827             reason = 'connected_to_hidden';
51828         }
51829         return action.disabled(context.graph()) || reason;
51830     };
51831
51832
51833     operation.tooltip = function() {
51834         var disable = operation.disabled();
51835         return disable ?
51836             t('operations.straighten.' + disable) :
51837             t('operations.straighten.description');
51838     };
51839
51840
51841     operation.id = 'straighten';
51842     operation.keys = [t('operations.straighten.key')];
51843     operation.title = t('operations.straighten.title');
51844     operation.behavior = behaviorOperation(context).which(operation);
51845
51846     return operation;
51847 }
51848
51849
51850
51851 var Operations = Object.freeze({
51852         operationCircularize: operationCircularize,
51853         operationContinue: operationContinue,
51854         operationDelete: operationDelete,
51855         operationDisconnect: operationDisconnect,
51856         operationMerge: operationMerge,
51857         operationMove: operationMove,
51858         operationOrthogonalize: operationOrthogonalize,
51859         operationReflectShort: operationReflectShort,
51860         operationReflectLong: operationReflectLong,
51861         operationReverse: operationReverse,
51862         operationRotate: operationRotate,
51863         operationSplit: operationSplit,
51864         operationStraighten: operationStraighten
51865 });
51866
51867 function modeMove$$1(context, entityIDs, baseGraph) {
51868     var mode = {
51869         id: 'move',
51870         button: 'browse'
51871     };
51872
51873     var keybinding = d3keybinding('move'),
51874         behaviors = [
51875             behaviorEdit(context),
51876             operationCircularize(entityIDs, context).behavior,
51877             operationDelete(entityIDs, context).behavior,
51878             operationOrthogonalize(entityIDs, context).behavior,
51879             operationReflectLong(entityIDs, context).behavior,
51880             operationReflectShort(entityIDs, context).behavior,
51881             operationRotate(entityIDs, context).behavior
51882         ],
51883         annotation = entityIDs.length === 1 ?
51884             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
51885             t('operations.move.annotation.multiple'),
51886         prevGraph,
51887         cache,
51888         origin,
51889         nudgeInterval;
51890
51891
51892     function vecSub(a, b) {
51893         return [a[0] - b[0], a[1] - b[1]];
51894     }
51895
51896
51897     function edge(point, size) {
51898         var pad = [30, 100, 30, 100],
51899             x = 0,
51900             y = 0;
51901
51902         if (point[0] > size[0] - pad[0])
51903             x = -10;
51904         if (point[0] < pad[2])
51905             x = 10;
51906         if (point[1] > size[1] - pad[1])
51907             y = -10;
51908         if (point[1] < pad[3])
51909             y = 10;
51910
51911         if (x || y) return [x, y];
51912         else return null;
51913     }
51914
51915
51916     function doMove(nudge) {
51917         nudge = nudge || [0, 0];
51918
51919         var fn;
51920         if (prevGraph !== context.graph()) {
51921             cache = {};
51922             origin = context.map().mouseCoordinates();
51923             fn = context.perform;
51924         } else {
51925             fn = context.overwrite;
51926         }
51927
51928         var currMouse = context.mouse(),
51929             origMouse = context.projection(origin),
51930             delta = vecSub(vecSub(currMouse, origMouse), nudge);
51931
51932         fn(actionMove(entityIDs, delta, context.projection, cache), annotation);
51933         prevGraph = context.graph();
51934     }
51935
51936
51937     function startNudge(nudge) {
51938         if (nudgeInterval) window.clearInterval(nudgeInterval);
51939         nudgeInterval = window.setInterval(function() {
51940             context.pan(nudge);
51941             doMove(nudge);
51942         }, 50);
51943     }
51944
51945
51946     function stopNudge() {
51947         if (nudgeInterval) window.clearInterval(nudgeInterval);
51948         nudgeInterval = null;
51949     }
51950
51951
51952     function move() {
51953         doMove();
51954         var nudge = edge(context.mouse(), context.map().dimensions());
51955         if (nudge) startNudge(nudge);
51956         else stopNudge();
51957     }
51958
51959
51960     function finish() {
51961         event.stopPropagation();
51962         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
51963         stopNudge();
51964     }
51965
51966
51967     function cancel() {
51968         if (baseGraph) {
51969             while (context.graph() !== baseGraph) context.pop();
51970             context.enter(modeBrowse(context));
51971         } else {
51972             context.pop();
51973             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
51974         }
51975         stopNudge();
51976     }
51977
51978
51979     function undone() {
51980         context.enter(modeBrowse(context));
51981     }
51982
51983
51984     mode.enter = function() {
51985         origin = context.map().mouseCoordinates();
51986         prevGraph = null;
51987         cache = {};
51988
51989         behaviors.forEach(function(behavior) {
51990             context.install(behavior);
51991         });
51992
51993         context.surface()
51994             .on('mousemove.move', move)
51995             .on('click.move', finish);
51996
51997         context.history()
51998             .on('undone.move', undone);
51999
52000         keybinding
52001             .on('⎋', cancel)
52002             .on('↩', finish);
52003
52004         select(document)
52005             .call(keybinding);
52006     };
52007
52008
52009     mode.exit = function() {
52010         stopNudge();
52011
52012         behaviors.forEach(function(behavior) {
52013             context.uninstall(behavior);
52014         });
52015
52016         context.surface()
52017             .on('mousemove.move', null)
52018             .on('click.move', null);
52019
52020         context.history()
52021             .on('undone.move', null);
52022
52023         keybinding.off();
52024     };
52025
52026
52027     return mode;
52028 }
52029
52030 function modeRotate$$1(context, entityIDs) {
52031     var mode = {
52032         id: 'rotate',
52033         button: 'browse'
52034     };
52035
52036     var keybinding = d3keybinding('rotate'),
52037         behaviors = [
52038             behaviorEdit(context),
52039             operationCircularize(entityIDs, context).behavior,
52040             operationDelete(entityIDs, context).behavior,
52041             operationMove(entityIDs, context).behavior,
52042             operationOrthogonalize(entityIDs, context).behavior,
52043             operationReflectLong(entityIDs, context).behavior,
52044             operationReflectShort(entityIDs, context).behavior
52045         ],
52046         annotation = entityIDs.length === 1 ?
52047             t('operations.rotate.annotation.' + context.geometry(entityIDs[0])) :
52048             t('operations.rotate.annotation.multiple'),
52049         prevGraph,
52050         prevAngle,
52051         prevTransform,
52052         pivot;
52053
52054
52055     function doRotate() {
52056         var fn;
52057         if (context.graph() !== prevGraph) {
52058             fn = context.perform;
52059         } else {
52060             fn = context.replace;
52061         }
52062
52063         // projection changed, recalculate pivot
52064         var projection = context.projection;
52065         var currTransform = projection.transform();
52066         if (!prevTransform ||
52067             currTransform.k !== prevTransform.k ||
52068             currTransform.x !== prevTransform.x ||
52069             currTransform.y !== prevTransform.y) {
52070
52071             var nodes = utilGetAllNodes(entityIDs, context.graph()),
52072                 points = nodes.map(function(n) { return projection(n.loc); });
52073
52074             pivot = d3polygonCentroid(d3polygonHull(points));
52075             prevAngle = undefined;
52076         }
52077
52078
52079         var currMouse = context.mouse(),
52080             currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);
52081
52082         if (typeof prevAngle === 'undefined') prevAngle = currAngle;
52083         var delta = currAngle - prevAngle;
52084
52085         fn(actionRotate(entityIDs, pivot, delta, projection), annotation);
52086
52087         prevTransform = currTransform;
52088         prevAngle = currAngle;
52089         prevGraph = context.graph();
52090     }
52091
52092
52093     function finish() {
52094         event.stopPropagation();
52095         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52096     }
52097
52098
52099     function cancel() {
52100         context.pop();
52101         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
52102     }
52103
52104
52105     function undone() {
52106         context.enter(modeBrowse(context));
52107     }
52108
52109
52110     mode.enter = function() {
52111         behaviors.forEach(function(behavior) {
52112             context.install(behavior);
52113         });
52114
52115         context.surface()
52116             .on('mousemove.rotate', doRotate)
52117             .on('click.rotate', finish);
52118
52119         context.history()
52120             .on('undone.rotate', undone);
52121
52122         keybinding
52123             .on('⎋', cancel)
52124             .on('↩', finish);
52125
52126         select(document)
52127             .call(keybinding);
52128     };
52129
52130
52131     mode.exit = function() {
52132         behaviors.forEach(function(behavior) {
52133             context.uninstall(behavior);
52134         });
52135
52136         context.surface()
52137             .on('mousemove.rotate', null)
52138             .on('click.rotate', null);
52139
52140         context.history()
52141             .on('undone.rotate', null);
52142
52143         keybinding.off();
52144     };
52145
52146
52147     return mode;
52148 }
52149
52150 function modeSave$$1(context) {
52151     var mode = {
52152         id: 'save'
52153     };
52154
52155     var ui = uiCommit(context)
52156             .on('cancel', cancel)
52157             .on('save', save);
52158
52159
52160     function cancel() {
52161         context.enter(modeBrowse(context));
52162     }
52163
52164
52165     function save(e, tryAgain) {
52166         function withChildNodes(ids, graph) {
52167             return lodash.uniq(lodash.reduce(ids, function(result, id) {
52168                 var e = graph.entity(id);
52169                 if (e.type === 'way') {
52170                     try {
52171                         var cn = graph.childNodes(e);
52172                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
52173                     } catch (err) {
52174                         /* eslint-disable no-console */
52175                         if (typeof console !== 'undefined') console.error(err);
52176                         /* eslint-enable no-console */
52177                     }
52178                 }
52179                 return result;
52180             }, lodash.clone(ids)));
52181         }
52182
52183         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
52184             history = context.history(),
52185             origChanges = history.changes(actionDiscardTags(history.difference())),
52186             localGraph = context.graph(),
52187             remoteGraph = coreGraph$$1(history.base(), true),
52188             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
52189             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
52190             toLoad = withChildNodes(toCheck, localGraph),
52191             conflicts = [],
52192             errors = [];
52193
52194         if (!tryAgain) history.perform(actionNoop());  // checkpoint
52195         context.container().call(loading);
52196
52197         if (toCheck.length) {
52198             context.connection().loadMultiple(toLoad, loaded);
52199         } else {
52200             finalize();
52201         }
52202
52203
52204         // Reload modified entities into an alternate graph and check for conflicts..
52205         function loaded(err, result) {
52206             if (errors.length) return;
52207
52208             if (err) {
52209                 errors.push({
52210                     msg: err.responseText,
52211                     details: [ t('save.status_code', { code: err.status }) ]
52212                 });
52213                 showErrors();
52214
52215             } else {
52216                 var loadMore = [];
52217                 lodash.each(result.data, function(entity) {
52218                     remoteGraph.replace(entity);
52219                     toLoad = lodash.without(toLoad, entity.id);
52220
52221                     // Because loadMultiple doesn't download /full like loadEntity,
52222                     // need to also load children that aren't already being checked..
52223                     if (!entity.visible) return;
52224                     if (entity.type === 'way') {
52225                         loadMore.push.apply(loadMore,
52226                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
52227                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
52228                         loadMore.push.apply(loadMore,
52229                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
52230                     }
52231                 });
52232
52233                 if (loadMore.length) {
52234                     toLoad.push.apply(toLoad, loadMore);
52235                     context.connection().loadMultiple(loadMore, loaded);
52236                 }
52237
52238                 if (!toLoad.length) {
52239                     checkConflicts();
52240                 }
52241             }
52242         }
52243
52244
52245         function checkConflicts() {
52246             function choice(id, text$$1, action) {
52247                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
52248             }
52249             function formatUser(d) {
52250                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
52251             }
52252             function entityName(entity) {
52253                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
52254             }
52255
52256             function compareVersions(local$$1, remote) {
52257                 if (local$$1.version !== remote.version) return false;
52258
52259                 if (local$$1.type === 'way') {
52260                     var children = lodash.union(local$$1.nodes, remote.nodes);
52261
52262                     for (var i = 0; i < children.length; i++) {
52263                         var a = localGraph.hasEntity(children[i]),
52264                             b = remoteGraph.hasEntity(children[i]);
52265
52266                         if (a && b && a.version !== b.version) return false;
52267                     }
52268                 }
52269
52270                 return true;
52271             }
52272
52273             lodash.each(toCheck, function(id) {
52274                 var local$$1 = localGraph.entity(id),
52275                     remote = remoteGraph.entity(id);
52276
52277                 if (compareVersions(local$$1, remote)) return;
52278
52279                 var action = actionMergeRemoteChanges,
52280                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
52281
52282                 history.replace(merge$$1);
52283
52284                 var mergeConflicts = merge$$1.conflicts();
52285                 if (!mergeConflicts.length) return;  // merged safely
52286
52287                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
52288                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
52289                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
52290                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
52291
52292                 conflicts.push({
52293                     id: id,
52294                     name: entityName(local$$1),
52295                     details: mergeConflicts,
52296                     chosen: 1,
52297                     choices: [
52298                         choice(id, keepMine, forceLocal),
52299                         choice(id, keepTheirs, forceRemote)
52300                     ]
52301                 });
52302             });
52303
52304             finalize();
52305         }
52306
52307
52308         function finalize() {
52309             if (conflicts.length) {
52310                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
52311                 showConflicts();
52312             } else if (errors.length) {
52313                 showErrors();
52314             } else {
52315                 var changes = history.changes(actionDiscardTags(history.difference()));
52316                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
52317                     context.connection().putChangeset(
52318                         changes,
52319                         context.version,
52320                         e.comment,
52321                         history.imageryUsed(),
52322                         function(err, changeset_id) {
52323                             if (err) {
52324                                 errors.push({
52325                                     msg: err.responseText,
52326                                     details: [ t('save.status_code', { code: err.status }) ]
52327                                 });
52328                                 showErrors();
52329                             } else {
52330                                 history.clearSaved();
52331                                 success(e, changeset_id);
52332                                 // Add delay to allow for postgres replication #1646 #2678
52333                                 window.setTimeout(function() {
52334                                     loading.close();
52335                                     context.flush();
52336                                 }, 2500);
52337                             }
52338                         });
52339                 } else {        // changes were insignificant or reverted by user
52340                     loading.close();
52341                     context.flush();
52342                     cancel();
52343                 }
52344             }
52345         }
52346
52347
52348         function showConflicts() {
52349             var selection$$1 = context.container()
52350                 .select('#sidebar')
52351                 .append('div')
52352                 .attr('class','sidebar-component');
52353
52354             loading.close();
52355
52356             selection$$1.call(uiConflicts(context)
52357                 .list(conflicts)
52358                 .on('download', function() {
52359                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
52360                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
52361                     win.focus();
52362                 })
52363                 .on('cancel', function() {
52364                     history.pop();
52365                     selection$$1.remove();
52366                 })
52367                 .on('save', function() {
52368                     for (var i = 0; i < conflicts.length; i++) {
52369                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
52370                             var entity = context.hasEntity(conflicts[i].id);
52371                             if (entity && entity.type === 'way') {
52372                                 var children = lodash.uniq(entity.nodes);
52373                                 for (var j = 0; j < children.length; j++) {
52374                                     history.replace(actionRevert(children[j]));
52375                                 }
52376                             }
52377                             history.replace(actionRevert(conflicts[i].id));
52378                         }
52379                     }
52380
52381                     selection$$1.remove();
52382                     save(e, true);
52383                 })
52384             );
52385         }
52386
52387
52388         function showErrors() {
52389             var selection$$1 = uiConfirm(context.container());
52390
52391             history.pop();
52392             loading.close();
52393
52394             selection$$1
52395                 .select('.modal-section.header')
52396                 .append('h3')
52397                 .text(t('save.error'));
52398
52399             addErrors(selection$$1, errors);
52400             selection$$1.okButton();
52401         }
52402
52403
52404         function addErrors(selection$$1, data) {
52405             var message = selection$$1
52406                 .select('.modal-section.message-text');
52407
52408             var items = message
52409                 .selectAll('.error-container')
52410                 .data(data);
52411
52412             var enter = items.enter()
52413                 .append('div')
52414                 .attr('class', 'error-container');
52415
52416             enter
52417                 .append('a')
52418                 .attr('class', 'error-description')
52419                 .attr('href', '#')
52420                 .classed('hide-toggle', true)
52421                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
52422                 .on('click', function() {
52423                     var error = select(this),
52424                         detail = select(this.nextElementSibling),
52425                         exp = error.classed('expanded');
52426
52427                     detail.style('display', exp ? 'none' : 'block');
52428                     error.classed('expanded', !exp);
52429
52430                     event.preventDefault();
52431                 });
52432
52433             var details = enter
52434                 .append('div')
52435                 .attr('class', 'error-detail-container')
52436                 .style('display', 'none');
52437
52438             details
52439                 .append('ul')
52440                 .attr('class', 'error-detail-list')
52441                 .selectAll('li')
52442                 .data(function(d) { return d.details || []; })
52443                 .enter()
52444                 .append('li')
52445                 .attr('class', 'error-detail-item')
52446                 .text(function(d) { return d; });
52447
52448             items.exit()
52449                 .remove();
52450         }
52451
52452     }
52453
52454
52455     function success(e, changeset_id) {
52456         context.enter(modeBrowse(context)
52457             .sidebar(uiSuccess(context)
52458                 .changeset({
52459                     id: changeset_id,
52460                     comment: e.comment
52461                 })
52462                 .on('cancel', function() {
52463                     context.ui().sidebar.hide();
52464                 })
52465             )
52466         );
52467     }
52468
52469
52470     mode.enter = function() {
52471         function done() {
52472             context.ui().sidebar.show(ui);
52473         }
52474
52475         context.container().selectAll('#content')
52476             .attr('class', 'inactive');
52477
52478         if (context.connection().authenticated()) {
52479             done();
52480         } else {
52481             context.connection().authenticate(function(err) {
52482                 if (err) {
52483                     cancel();
52484                 } else {
52485                     done();
52486                 }
52487             });
52488         }
52489     };
52490
52491
52492     mode.exit = function() {
52493         context.container().selectAll('#content')
52494             .attr('class', 'active');
52495
52496         context.ui().sidebar.hide();
52497     };
52498
52499     return mode;
52500 }
52501
52502 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
52503 // For example, ⌘Z -> Ctrl+Z
52504 function uiCmd(code) {
52505     var detected = utilDetect();
52506
52507     if (detected.os === 'mac') {
52508         return code;
52509     }
52510
52511     if (detected.os === 'win') {
52512         if (code === '⌘⇧Z') return 'Ctrl+Y';
52513     }
52514
52515     var result = '',
52516         replacements = {
52517             '⌘': 'Ctrl',
52518             '⇧': 'Shift',
52519             '⌥': 'Alt',
52520             '⌫': 'Backspace',
52521             '⌦': 'Delete'
52522         };
52523
52524     for (var i = 0; i < code.length; i++) {
52525         if (code[i] in replacements) {
52526             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
52527         } else {
52528             result += code[i];
52529         }
52530     }
52531
52532     return result;
52533 }
52534
52535 var relatedParent;
52536
52537
52538 function modeSelect(context, selectedIDs) {
52539     var mode = {
52540         id: 'select',
52541         button: 'browse'
52542     };
52543
52544     var keybinding = d3keybinding('select'),
52545         timeout$$1 = null,
52546         behaviors = [
52547             behaviorCopy(context),
52548             behaviorPaste(context),
52549             behaviorBreathe(context),
52550             behaviorHover(context),
52551             behaviorSelect(context),
52552             behaviorLasso(context),
52553             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
52554         ],
52555         inspector,
52556         radialMenu,
52557         newFeature = false,
52558         suppressMenu = false,
52559         follow = false;
52560
52561
52562     var wrap = context.container()
52563         .select('.inspector-wrap');
52564
52565
52566     function singular() {
52567         if (selectedIDs.length === 1) {
52568             return context.hasEntity(selectedIDs[0]);
52569         }
52570     }
52571
52572
52573     function checkSelectedIDs() {
52574         var ids = [];
52575         if (Array.isArray(selectedIDs)) {
52576             ids = selectedIDs.filter(function(id) {
52577                 return context.hasEntity(id);
52578             });
52579         }
52580
52581         if (ids.length) {
52582             selectedIDs = ids;
52583         } else {
52584             context.enter(modeBrowse(context));
52585         }
52586         return !!ids.length;
52587     }
52588
52589
52590     // find the common parent ways for nextVertex, previousVertex
52591     function commonParents() {
52592         var graph = context.graph(),
52593             commonParents = [];
52594
52595         for (var i = 0; i < selectedIDs.length; i++) {
52596             var entity = context.hasEntity(selectedIDs[i]);
52597             if (!entity || entity.geometry(graph) !== 'vertex') {
52598                 return [];  // selection includes some not vertexes
52599             }
52600
52601             var currParents = lodash.map(graph.parentWays(entity), 'id');
52602             if (!commonParents.length) {
52603                 commonParents = currParents;
52604                 continue;
52605             }
52606
52607             commonParents = lodash.intersection(commonParents, currParents);
52608             if (!commonParents.length) {
52609                 return [];
52610             }
52611         }
52612
52613         return commonParents;
52614     }
52615
52616
52617     function singularParent() {
52618         var parents = commonParents();
52619         if (!parents || parents.length === 0) {
52620             relatedParent = null;
52621             return null;
52622         }
52623
52624         // relatedParent is used when we visit a vertex with multiple
52625         // parents, and we want to remember which parent line we started on.
52626
52627         if (parents.length === 1) {
52628             relatedParent = parents[0];  // remember this parent for later
52629             return relatedParent;
52630         }
52631
52632         if (parents.indexOf(relatedParent) !== -1) {
52633             return relatedParent;   // prefer the previously seen parent
52634         }
52635
52636         return parents[0];
52637     }
52638
52639
52640     function closeMenu() {
52641         if (radialMenu) {
52642             context.surface().call(radialMenu.close);
52643         }
52644     }
52645
52646
52647     function positionMenu() {
52648         if (suppressMenu || !radialMenu) { return; }
52649
52650         var entity = singular();
52651         if (entity && context.geometry(entity.id) === 'relation') {
52652             suppressMenu = true;
52653         } else if (entity && entity.type === 'node') {
52654             radialMenu.center(context.projection(entity.loc));
52655         } else {
52656             var point = context.mouse(),
52657                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
52658             if (geoPointInPolygon(point, viewport)) {
52659                 radialMenu.center(point);
52660             } else {
52661                 suppressMenu = true;
52662             }
52663         }
52664     }
52665
52666
52667     function showMenu() {
52668         closeMenu();
52669         if (!suppressMenu && radialMenu) {
52670             context.surface().call(radialMenu);
52671         }
52672     }
52673
52674
52675     function toggleMenu() {
52676         if (select('.radial-menu').empty()) {
52677             showMenu();
52678         } else {
52679             closeMenu();
52680         }
52681     }
52682
52683
52684     mode.selectedIDs = function() {
52685         return selectedIDs;
52686     };
52687
52688
52689     mode.reselect = function() {
52690         if (!checkSelectedIDs()) return;
52691
52692         var surfaceNode = context.surface().node();
52693         if (surfaceNode.focus) {   // FF doesn't support it
52694             surfaceNode.focus();
52695         }
52696
52697         positionMenu();
52698         showMenu();
52699     };
52700
52701
52702     mode.newFeature = function(_) {
52703         if (!arguments.length) return newFeature;
52704         newFeature = _;
52705         return mode;
52706     };
52707
52708
52709     mode.suppressMenu = function(_) {
52710         if (!arguments.length) return suppressMenu;
52711         suppressMenu = _;
52712         return mode;
52713     };
52714
52715
52716     mode.follow = function(_) {
52717         if (!arguments.length) return follow;
52718         follow = _;
52719         return mode;
52720     };
52721
52722
52723     mode.enter = function() {
52724
52725         function update() {
52726             closeMenu();
52727             checkSelectedIDs();
52728         }
52729
52730
52731         function dblclick() {
52732             var target = select(event.target),
52733                 datum = target.datum();
52734
52735             if (datum instanceof osmWay && !target.classed('fill')) {
52736                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
52737                     prev = datum.nodes[choice.index - 1],
52738                     next = datum.nodes[choice.index];
52739
52740                 context.perform(
52741                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, osmNode()),
52742                     t('operations.add.annotation.vertex')
52743                 );
52744
52745                 event.preventDefault();
52746                 event.stopPropagation();
52747             } else if (datum.type === 'midpoint') {
52748                 context.perform(
52749                     actionAddMidpoint({loc: datum.loc, edge: datum.edge}, osmNode()),
52750                     t('operations.add.annotation.vertex'));
52751
52752                 event.preventDefault();
52753                 event.stopPropagation();
52754             }
52755         }
52756
52757
52758         function selectElements(drawn) {
52759             if (!checkSelectedIDs()) return;
52760
52761             var surface = context.surface(),
52762                 entity = singular();
52763
52764             if (entity && context.geometry(entity.id) === 'relation') {
52765                 suppressMenu = true;
52766                 return;
52767             }
52768
52769             surface.selectAll('.related')
52770                 .classed('related', false);
52771
52772             singularParent();
52773             if (relatedParent) {
52774                 surface.selectAll(utilEntitySelector([relatedParent]))
52775                     .classed('related', true);
52776             }
52777
52778             var selection$$1 = context.surface()
52779                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
52780
52781             if (selection$$1.empty()) {
52782                 // Return to browse mode if selected DOM elements have
52783                 // disappeared because the user moved them out of view..
52784                 var source = event && event.type === 'zoom' && event.sourceEvent;
52785                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
52786                     context.enter(modeBrowse(context));
52787                 }
52788             } else {
52789                 selection$$1
52790                     .classed('selected', true);
52791             }
52792         }
52793
52794
52795         function esc() {
52796             if (!context.inIntro()) {
52797                 context.enter(modeBrowse(context));
52798             }
52799         }
52800
52801
52802         function firstVertex() {
52803             event.preventDefault();
52804             var parent = singularParent();
52805             if (parent) {
52806                 var way = context.entity(parent);
52807                 context.enter(
52808                     modeSelect(context, [way.first()]).follow(true).suppressMenu(true)
52809                 );
52810             }
52811         }
52812
52813
52814         function lastVertex() {
52815             event.preventDefault();
52816             var parent = singularParent();
52817             if (parent) {
52818                 var way = context.entity(parent);
52819                 context.enter(
52820                     modeSelect(context, [way.last()]).follow(true).suppressMenu(true)
52821                 );
52822             }
52823         }
52824
52825
52826         function previousVertex() {
52827             event.preventDefault();
52828             var parent = singularParent();
52829             if (!parent) return;
52830
52831             var way = context.entity(parent),
52832                 length = way.nodes.length,
52833                 curr = way.nodes.indexOf(selectedIDs[0]),
52834                 index = -1;
52835
52836             if (curr > 0) {
52837                 index = curr - 1;
52838             } else if (way.isClosed()) {
52839                 index = length - 2;
52840             }
52841
52842             if (index !== -1) {
52843                 context.enter(
52844                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52845                 );
52846             }
52847         }
52848
52849
52850         function nextVertex() {
52851             event.preventDefault();
52852             var parent = singularParent();
52853             if (!parent) return;
52854
52855             var way = context.entity(parent),
52856                 length = way.nodes.length,
52857                 curr = way.nodes.indexOf(selectedIDs[0]),
52858                 index = -1;
52859
52860             if (curr < length - 1) {
52861                 index = curr + 1;
52862             } else if (way.isClosed()) {
52863                 index = 0;
52864             }
52865
52866             if (index !== -1) {
52867                 context.enter(
52868                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52869                 );
52870             }
52871         }
52872
52873
52874         function nextParent() {
52875             event.preventDefault();
52876             var parents = lodash.uniq(commonParents());
52877             if (!parents || parents.length < 2) return;
52878
52879             var index = parents.indexOf(relatedParent);
52880             if (index < 0 || index > parents.length - 2) {
52881                 relatedParent = parents[0];
52882             } else {
52883                 relatedParent = parents[index + 1];
52884             }
52885
52886             var surface = context.surface();
52887             surface.selectAll('.related')
52888                 .classed('related', false);
52889
52890             if (relatedParent) {
52891                 surface.selectAll(utilEntitySelector([relatedParent]))
52892                     .classed('related', true);
52893             }
52894         }
52895
52896
52897         if (!checkSelectedIDs()) return;
52898
52899         var operations = lodash.without(values(Operations), operationDelete)
52900                 .map(function(o) { return o(selectedIDs, context); })
52901                 .filter(function(o) { return o.available(); });
52902
52903         operations.unshift(operationDelete(selectedIDs, context));
52904
52905         operations.forEach(function(operation) {
52906             if (operation.behavior) {
52907                 behaviors.push(operation.behavior);
52908             }
52909         });
52910
52911         behaviors.forEach(function(behavior) {
52912             context.install(behavior);
52913         });
52914
52915         keybinding
52916             .on(['[','pgup'], previousVertex)
52917             .on([']', 'pgdown'], nextVertex)
52918             .on([uiCmd('⌘['), 'home'], firstVertex)
52919             .on([uiCmd('⌘]'), 'end'], lastVertex)
52920             .on(['\\', 'pause'], nextParent)
52921             .on('⎋', esc, true)
52922             .on('space', toggleMenu);
52923
52924         select(document)
52925             .call(keybinding);
52926
52927         radialMenu = uiRadialMenu(context, operations);
52928
52929         context.ui().sidebar
52930             .select(singular() ? singular().id : null, newFeature);
52931
52932         context.history()
52933             .on('undone.select', update)
52934             .on('redone.select', update);
52935
52936         context.map()
52937             .on('move.select', closeMenu)
52938             .on('drawn.select', selectElements);
52939
52940         selectElements();
52941
52942         var show = event && !suppressMenu;
52943
52944         if (show) {
52945             positionMenu();
52946         }
52947
52948         if (follow) {
52949             var extent$$1 = geoExtent$$1(),
52950                 graph = context.graph();
52951             selectedIDs.forEach(function(id) {
52952                 var entity = context.entity(id);
52953                 extent$$1._extend(entity.extent(graph));
52954             });
52955
52956             var loc = extent$$1.center();
52957             context.map().centerEase(loc);
52958         }
52959
52960         timeout$$1 = window.setTimeout(function() {
52961             if (show) {
52962                 showMenu();
52963             }
52964
52965             context.surface()
52966                 .on('dblclick.select', dblclick);
52967         }, 200);
52968
52969         if (selectedIDs.length > 1) {
52970             var entities = uiSelectionList(context, selectedIDs);
52971             context.ui().sidebar.show(entities);
52972         }
52973     };
52974
52975
52976     mode.exit = function() {
52977         if (timeout$$1) window.clearTimeout(timeout$$1);
52978
52979         if (inspector) wrap.call(inspector.close);
52980
52981         behaviors.forEach(function(behavior) {
52982             context.uninstall(behavior);
52983         });
52984
52985         keybinding.off();
52986         closeMenu();
52987         radialMenu = undefined;
52988
52989         context.history()
52990             .on('undone.select', null)
52991             .on('redone.select', null);
52992
52993         var surface = context.surface();
52994
52995         surface
52996             .on('dblclick.select', null);
52997
52998         surface
52999             .selectAll('.selected')
53000             .classed('selected', false);
53001
53002         surface
53003             .selectAll('.related')
53004             .classed('related', false);
53005
53006         context.map().on('drawn.select', null);
53007         context.ui().sidebar.hide();
53008     };
53009
53010
53011     return mode;
53012 }
53013
53014 function uiAccount(context) {
53015     var connection = context.connection();
53016
53017
53018     function update(selection$$1) {
53019         if (!connection.authenticated()) {
53020             selection$$1.selectAll('#userLink, #logoutLink')
53021                 .classed('hide', true);
53022             return;
53023         }
53024
53025         connection.userDetails(function(err, details) {
53026             var userLink = selection$$1.select('#userLink'),
53027                 logoutLink = selection$$1.select('#logoutLink');
53028
53029             userLink.html('');
53030             logoutLink.html('');
53031
53032             if (err) return;
53033
53034             selection$$1.selectAll('#userLink, #logoutLink')
53035                 .classed('hide', false);
53036
53037             // Link
53038             userLink.append('a')
53039                 .attr('href', connection.userURL(details.display_name))
53040                 .attr('target', '_blank');
53041
53042             // Add thumbnail or dont
53043             if (details.image_url) {
53044                 userLink.append('img')
53045                     .attr('class', 'icon pre-text user-icon')
53046                     .attr('src', details.image_url);
53047             } else {
53048                 userLink
53049                     .call(svgIcon('#icon-avatar', 'pre-text light'));
53050             }
53051
53052             // Add user name
53053             userLink.append('span')
53054                 .attr('class', 'label')
53055                 .text(details.display_name);
53056
53057             logoutLink.append('a')
53058                 .attr('class', 'logout')
53059                 .attr('href', '#')
53060                 .text(t('logout'))
53061                 .on('click.logout', function() {
53062                     event.preventDefault();
53063                     connection.logout();
53064                 });
53065         });
53066     }
53067
53068
53069     return function(selection$$1) {
53070         selection$$1.append('li')
53071             .attr('id', 'logoutLink')
53072             .classed('hide', true);
53073
53074         selection$$1.append('li')
53075             .attr('id', 'userLink')
53076             .classed('hide', true);
53077
53078         connection
53079             .on('change.account', function() { update(selection$$1); });
53080
53081         update(selection$$1);
53082     };
53083 }
53084
53085 function uiAttribution(context) {
53086     var selection$$1;
53087
53088
53089     function attribution(data, klass) {
53090         var div = selection$$1.selectAll('.' + klass)
53091             .data([0]);
53092
53093         div = div.enter()
53094             .append('div')
53095             .attr('class', klass)
53096             .merge(div);
53097
53098
53099         var background = div.selectAll('.attribution')
53100             .data(data, function(d) { return d.name(); });
53101
53102         background.exit()
53103             .remove();
53104
53105         background = background.enter()
53106             .append('span')
53107             .attr('class', 'attribution')
53108             .each(function(d) {
53109                 if (d.terms_html) {
53110                     select(this)
53111                         .html(d.terms_html);
53112                     return;
53113                 }
53114
53115                 var source = d.terms_text || d.id || d.name();
53116
53117                 if (d.logo) {
53118                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
53119                 }
53120
53121                 if (d.terms_url) {
53122                     select(this)
53123                         .append('a')
53124                         .attr('href', d.terms_url)
53125                         .attr('target', '_blank')
53126                         .html(source);
53127                 } else {
53128                     select(this)
53129                         .text(source);
53130                 }
53131             })
53132             .merge(background);
53133
53134
53135         var copyright = background.selectAll('.copyright-notice')
53136             .data(function(d) {
53137                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
53138                 return notice ? [notice] : [];
53139             });
53140
53141         copyright.exit()
53142             .remove();
53143
53144         copyright = copyright.enter()
53145             .append('span')
53146             .attr('class', 'copyright-notice')
53147             .merge(copyright);
53148
53149         copyright
53150             .text(String);
53151     }
53152
53153
53154     function update() {
53155         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
53156         attribution(context.background().overlayLayerSources().filter(function (s) {
53157             return s.validZoom(context.map().zoom());
53158         }), 'overlay-layer-attribution');
53159     }
53160
53161
53162     return function(select$$1) {
53163         selection$$1 = select$$1;
53164
53165         context.background()
53166             .on('change.attribution', update);
53167
53168         context.map()
53169             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
53170
53171         update();
53172     };
53173 }
53174
53175 function rendererBackgroundSource(data) {
53176     var source = lodash.clone(data),
53177         offset = [0, 0],
53178         name = source.name,
53179         best = !!source.best;
53180
53181     source.scaleExtent = data.scaleExtent || [0, 20];
53182     source.overzoom = data.overzoom !== false;
53183
53184
53185     source.offset = function(_) {
53186         if (!arguments.length) return offset;
53187         offset = _;
53188         return source;
53189     };
53190
53191
53192     source.nudge = function(_, zoomlevel) {
53193         offset[0] += _[0] / Math.pow(2, zoomlevel);
53194         offset[1] += _[1] / Math.pow(2, zoomlevel);
53195         return source;
53196     };
53197
53198
53199     source.name = function() {
53200         return name;
53201     };
53202
53203
53204     source.best = function() {
53205         return best;
53206     };
53207
53208
53209     source.area = function() {
53210         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
53211         var area$$1 = area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
53212         return isNaN(area$$1) ? 0 : area$$1;
53213     };
53214
53215
53216     source.imageryUsed = function() {
53217         return name || source.id;
53218     };
53219
53220
53221     source.url = function(coord) {
53222         return data.template
53223             .replace('{x}', coord[0])
53224             .replace('{y}', coord[1])
53225             // TMS-flipped y coordinate
53226             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
53227             .replace(/\{z(oom)?\}/, coord[2])
53228             .replace(/\{switch:([^}]+)\}/, function(s, r) {
53229                 var subdomains = r.split(',');
53230                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
53231             })
53232             .replace('{u}', function() {
53233                 var u = '';
53234                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
53235                     var b = 0;
53236                     var mask = 1 << (zoom$$1 - 1);
53237                     if ((coord[0] & mask) !== 0) b++;
53238                     if ((coord[1] & mask) !== 0) b += 2;
53239                     u += b.toString();
53240                 }
53241                 return u;
53242             });
53243     };
53244
53245
53246     source.intersects = function(extent$$1) {
53247         extent$$1 = extent$$1.polygon();
53248         return !data.polygon || data.polygon.some(function(polygon) {
53249             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
53250         });
53251     };
53252
53253
53254     source.validZoom = function(z) {
53255         return source.scaleExtent[0] <= z &&
53256             (source.overzoom || source.scaleExtent[1] > z);
53257     };
53258
53259
53260     source.isLocatorOverlay = function() {
53261         return source.id === 'mapbox_locator_overlay';
53262     };
53263
53264
53265     source.copyrightNotices = function() {};
53266
53267
53268     return source;
53269 }
53270
53271
53272 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
53273     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
53274     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
53275
53276     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
53277
53278     var bing = rendererBackgroundSource(data),
53279         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
53280         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
53281             key + '&jsonp={callback}',
53282         providers = [];
53283
53284     jsonpRequest(url, function(json$$1) {
53285         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
53286             return {
53287                 attribution: provider.attribution,
53288                 areas: provider.coverageAreas.map(function(area$$1) {
53289                     return {
53290                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
53291                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
53292                     };
53293                 })
53294             };
53295         });
53296         dispatch$$1.call('change');
53297     });
53298
53299     bing.copyrightNotices = function(zoom$$1, extent$$1) {
53300         zoom$$1 = Math.min(zoom$$1, 21);
53301         return providers.filter(function(provider) {
53302             return lodash.some(provider.areas, function(area$$1) {
53303                 return extent$$1.intersects(area$$1.extent) &&
53304                     area$$1.zoom[0] <= zoom$$1 &&
53305                     area$$1.zoom[1] >= zoom$$1;
53306             });
53307         }).map(function(provider) {
53308             return provider.attribution;
53309         }).join(', ');
53310     };
53311
53312     bing.logo = 'bing_maps.png';
53313     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
53314
53315     return bing;
53316 };
53317
53318
53319 rendererBackgroundSource.None = function() {
53320     var source = rendererBackgroundSource({ id: 'none', template: '' });
53321
53322     source.name = function() {
53323         return t('background.none');
53324     };
53325
53326     source.imageryUsed = function() {
53327         return 'None';
53328     };
53329
53330     source.area = function() {
53331         return -1;  // sources in background pane are sorted by area
53332     };
53333
53334     return source;
53335 };
53336
53337
53338 rendererBackgroundSource.Custom = function(template) {
53339     var source = rendererBackgroundSource({ id: 'custom', template: template });
53340
53341     source.name = function() {
53342         return t('background.custom');
53343     };
53344
53345     source.imageryUsed = function() {
53346         return 'Custom (' + template + ')';
53347     };
53348
53349     source.area = function() {
53350         return -2;  // sources in background pane are sorted by area
53351     };
53352
53353     return source;
53354 };
53355
53356 function rendererTileLayer(context) {
53357     var tileSize = 256,
53358         tile = d3geoTile(),
53359         projection,
53360         cache = {},
53361         tileOrigin,
53362         z,
53363         transformProp = utilPrefixCSSProperty('Transform'),
53364         source = rendererBackgroundSource.None();
53365
53366
53367     // blacklist overlay tiles around Null Island..
53368     function nearNullIsland(x, y, z) {
53369         if (z >= 7) {
53370             var center = Math.pow(2, z - 1),
53371                 width = Math.pow(2, z - 6),
53372                 min$$1 = center - (width / 2),
53373                 max$$1 = center + (width / 2) - 1;
53374             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
53375         }
53376         return false;
53377     }
53378
53379
53380     function tileSizeAtZoom(d, z) {
53381         var epsilon = 0.002;
53382         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
53383     }
53384
53385
53386     function atZoom(t, distance) {
53387         var power = Math.pow(2, distance);
53388         return [
53389             Math.floor(t[0] * power),
53390             Math.floor(t[1] * power),
53391             t[2] + distance];
53392     }
53393
53394
53395     function lookUp(d) {
53396         for (var up = -1; up > -d[2]; up--) {
53397             var tile = atZoom(d, up);
53398             if (cache[source.url(tile)] !== false) {
53399                 return tile;
53400             }
53401         }
53402     }
53403
53404
53405     function uniqueBy(a, n) {
53406         var o = [], seen = {};
53407         for (var i = 0; i < a.length; i++) {
53408             if (seen[a[i][n]] === undefined) {
53409                 o.push(a[i]);
53410                 seen[a[i][n]] = true;
53411             }
53412         }
53413         return o;
53414     }
53415
53416
53417     function addSource(d) {
53418         d.push(source.url(d));
53419         return d;
53420     }
53421
53422
53423     // Update tiles based on current state of `projection`.
53424     function background(selection$$1) {
53425         tile.scale(projection.scale() * 2 * Math.PI)
53426             .translate(projection.translate());
53427
53428         tileOrigin = [
53429             projection.scale() * Math.PI - projection.translate()[0],
53430             projection.scale() * Math.PI - projection.translate()[1]];
53431
53432         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
53433
53434         render(selection$$1);
53435     }
53436
53437
53438     // Derive the tiles onscreen, remove those offscreen and position them.
53439     // Important that this part not depend on `projection` because it's
53440     // rentered when tiles load/error (see #644).
53441     function render(selection$$1) {
53442         var requests = [];
53443         var showDebug = context.getDebug('tile') && !source.overlay;
53444
53445         if (source.validZoom(z)) {
53446             tile().forEach(function(d) {
53447                 addSource(d);
53448                 if (d[3] === '') return;
53449                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
53450                 requests.push(d);
53451                 if (cache[d[3]] === false && lookUp(d)) {
53452                     requests.push(addSource(lookUp(d)));
53453                 }
53454             });
53455
53456             requests = uniqueBy(requests, 3).filter(function(r) {
53457                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
53458                     return false;
53459                 }
53460                 // don't re-request tiles which have failed in the past
53461                 return cache[r[3]] !== false;
53462             });
53463         }
53464
53465         var pixelOffset = [
53466             source.offset()[0] * Math.pow(2, z),
53467             source.offset()[1] * Math.pow(2, z)
53468         ];
53469
53470         function load(d) {
53471             cache[d[3]] = true;
53472             select(this)
53473                 .on('error', null)
53474                 .on('load', null)
53475                 .classed('tile-loaded', true);
53476             render(selection$$1);
53477         }
53478
53479         function error(d) {
53480             cache[d[3]] = false;
53481             select(this)
53482                 .on('error', null)
53483                 .on('load', null)
53484                 .remove();
53485             render(selection$$1);
53486         }
53487
53488         function imageTransform(d) {
53489             var _ts = tileSize * Math.pow(2, z - d[2]);
53490             var scale = tileSizeAtZoom(d, z);
53491             return 'translate(' +
53492                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
53493                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
53494                 'scale(' + scale + ',' + scale + ')';
53495         }
53496
53497         function debugTransform(d) {
53498             var _ts = tileSize * Math.pow(2, z - d[2]);
53499             var scale = tileSizeAtZoom(d, z);
53500             return 'translate(' +
53501                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
53502                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
53503         }
53504
53505
53506         var image = selection$$1.selectAll('img')
53507             .data(requests, function(d) { return d[3]; });
53508
53509         image.exit()
53510             .style(transformProp, imageTransform)
53511             .classed('tile-removing', true)
53512             .each(function() {
53513                 var tile = select(this);
53514                 window.setTimeout(function() {
53515                     if (tile.classed('tile-removing')) {
53516                         tile.remove();
53517                     }
53518                 }, 300);
53519             });
53520
53521         image.enter()
53522           .append('img')
53523             .attr('class', 'tile')
53524             .attr('src', function(d) { return d[3]; })
53525             .on('error', error)
53526             .on('load', load)
53527           .merge(image)
53528             .style(transformProp, imageTransform)
53529             .classed('tile-debug', showDebug)
53530             .classed('tile-removing', false);
53531
53532
53533         var debug = selection$$1.selectAll('.tile-label-debug')
53534             .data(showDebug ? requests : [], function(d) { return d[3]; });
53535
53536         debug.exit()
53537             .remove();
53538
53539         debug.enter()
53540           .append('div')
53541             .attr('class', 'tile-label-debug')
53542           .merge(debug)
53543             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
53544             .style(transformProp, debugTransform);
53545     }
53546
53547
53548     background.projection = function(_) {
53549         if (!arguments.length) return projection;
53550         projection = _;
53551         return background;
53552     };
53553
53554
53555     background.dimensions = function(_) {
53556         if (!arguments.length) return tile.size();
53557         tile.size(_);
53558         return background;
53559     };
53560
53561
53562     background.source = function(_) {
53563         if (!arguments.length) return source;
53564         source = _;
53565         cache = {};
53566         tile.scaleExtent(source.scaleExtent);
53567         return background;
53568     };
53569
53570
53571     return background;
53572 }
53573
53574 function rendererBackground(context) {
53575     var dispatch$$1 = dispatch('change'),
53576         baseLayer = rendererTileLayer(context).projection(context.projection),
53577         overlayLayers = [],
53578         backgroundSources;
53579
53580
53581     function findSource(id) {
53582         return lodash.find(backgroundSources, function(d) {
53583             return d.id && d.id === id;
53584         });
53585     }
53586
53587
53588     function background(selection$$1) {
53589         var base = selection$$1.selectAll('.layer-background')
53590             .data([0]);
53591
53592         base.enter()
53593             .insert('div', '.layer-data')
53594             .attr('class', 'layer layer-background')
53595             .merge(base)
53596             .call(baseLayer);
53597
53598         var overlays = selection$$1.selectAll('.layer-overlay')
53599             .data(overlayLayers, function(d) { return d.source().name(); });
53600
53601         overlays.exit()
53602             .remove();
53603
53604         overlays.enter()
53605             .insert('div', '.layer-data')
53606             .attr('class', 'layer layer-overlay')
53607             .merge(overlays)
53608             .each(function(layer) { select(this).call(layer); });
53609     }
53610
53611
53612     background.updateImagery = function() {
53613         var b = background.baseLayerSource(),
53614             o = overlayLayers
53615                 .filter(function (d) { return !d.source().isLocatorOverlay(); })
53616                 .map(function (d) { return d.source().id; })
53617                 .join(','),
53618             meters = geoOffsetToMeters(b.offset()),
53619             epsilon = 0.01,
53620             x = +meters[0].toFixed(2),
53621             y = +meters[1].toFixed(2),
53622             q = utilStringQs(window.location.hash.substring(1));
53623
53624         var id = b.id;
53625         if (id === 'custom') {
53626             id = 'custom:' + b.template;
53627         }
53628
53629         if (id) {
53630             q.background = id;
53631         } else {
53632             delete q.background;
53633         }
53634
53635         if (o) {
53636             q.overlays = o;
53637         } else {
53638             delete q.overlays;
53639         }
53640
53641         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
53642             q.offset = x + ',' + y;
53643         } else {
53644             delete q.offset;
53645         }
53646
53647         window.location.replace('#' + utilQsString(q, true));
53648
53649         var imageryUsed = [b.imageryUsed()];
53650
53651         overlayLayers
53652             .filter(function (d) { return !d.source().isLocatorOverlay(); })
53653             .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
53654
53655         var gpx = context.layers().layer('gpx');
53656         if (gpx && gpx.enabled() && gpx.hasGpx()) {
53657             imageryUsed.push('Local GPX');
53658         }
53659
53660         var mapillary_images = context.layers().layer('mapillary-images');
53661         if (mapillary_images && mapillary_images.enabled()) {
53662             imageryUsed.push('Mapillary Images');
53663         }
53664
53665         var mapillary_signs = context.layers().layer('mapillary-signs');
53666         if (mapillary_signs && mapillary_signs.enabled()) {
53667             imageryUsed.push('Mapillary Signs');
53668         }
53669
53670         context.history().imageryUsed(imageryUsed);
53671     };
53672
53673
53674     background.sources = function(extent$$1) {
53675         return backgroundSources.filter(function(source) {
53676             return source.intersects(extent$$1);
53677         });
53678     };
53679
53680
53681     background.dimensions = function(_) {
53682         if (!_) return;
53683         baseLayer.dimensions(_);
53684
53685         overlayLayers.forEach(function(layer) {
53686             layer.dimensions(_);
53687         });
53688     };
53689
53690
53691     background.baseLayerSource = function(d) {
53692         if (!arguments.length) return baseLayer.source();
53693
53694         // test source against OSM imagery blacklists..
53695         var blacklists = context.connection().imageryBlacklists();
53696
53697         var fail = false,
53698             tested = 0,
53699             regex, i;
53700
53701         for (i = 0; i < blacklists; i++) {
53702             try {
53703                 regex = new RegExp(blacklists[i]);
53704                 fail = regex.test(d.template);
53705                 tested++;
53706                 if (fail) break;
53707             } catch (e) {
53708                 /* noop */
53709             }
53710         }
53711
53712         // ensure at least one test was run.
53713         if (!tested) {
53714             regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
53715             fail = regex.test(d.template);
53716         }
53717
53718         baseLayer.source(!fail ? d : rendererBackgroundSource.None());
53719         dispatch$$1.call('change');
53720         background.updateImagery();
53721         return background;
53722     };
53723
53724
53725     background.bing = function() {
53726         background.baseLayerSource(findSource('Bing'));
53727     };
53728
53729
53730     background.showsLayer = function(d) {
53731         return d.id === baseLayer.source().id ||
53732             overlayLayers.some(function(layer) { return d.id === layer.source().id; });
53733     };
53734
53735
53736     background.overlayLayerSources = function() {
53737         return overlayLayers.map(function (l) { return l.source(); });
53738     };
53739
53740
53741     background.toggleOverlayLayer = function(d) {
53742         var layer;
53743
53744         for (var i = 0; i < overlayLayers.length; i++) {
53745             layer = overlayLayers[i];
53746             if (layer.source() === d) {
53747                 overlayLayers.splice(i, 1);
53748                 dispatch$$1.call('change');
53749                 background.updateImagery();
53750                 return;
53751             }
53752         }
53753
53754         layer = rendererTileLayer(context)
53755             .source(d)
53756             .projection(context.projection)
53757             .dimensions(baseLayer.dimensions());
53758
53759         overlayLayers.push(layer);
53760         dispatch$$1.call('change');
53761         background.updateImagery();
53762     };
53763
53764
53765     background.nudge = function(d, zoom$$1) {
53766         baseLayer.source().nudge(d, zoom$$1);
53767         dispatch$$1.call('change');
53768         background.updateImagery();
53769         return background;
53770     };
53771
53772
53773     background.offset = function(d) {
53774         if (!arguments.length) return baseLayer.source().offset();
53775         baseLayer.source().offset(d);
53776         dispatch$$1.call('change');
53777         background.updateImagery();
53778         return background;
53779     };
53780
53781
53782     background.init = function() {
53783         function parseMap(qmap) {
53784             if (!qmap) return false;
53785             var args = qmap.split('/').map(Number);
53786             if (args.length < 3 || args.some(isNaN)) return false;
53787             return geoExtent$$1([args[2], args[1]]);
53788         }
53789
53790         var dataImagery = data.imagery || [],
53791             q = utilStringQs(window.location.hash.substring(1)),
53792             chosen = q.background || q.layer,
53793             extent$$1 = parseMap(q.map),
53794             best;
53795
53796         backgroundSources = dataImagery.map(function(source) {
53797             if (source.type === 'bing') {
53798                 return rendererBackgroundSource.Bing(source, dispatch$$1);
53799             } else {
53800                 return rendererBackgroundSource(source);
53801             }
53802         });
53803
53804         backgroundSources.unshift(rendererBackgroundSource.None());
53805
53806         if (!chosen && extent$$1) {
53807             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
53808         }
53809
53810         if (chosen && chosen.indexOf('custom:') === 0) {
53811             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
53812         } else {
53813             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
53814         }
53815
53816         var locator = lodash.find(backgroundSources, function(d) {
53817             return d.overlay && d.default;
53818         });
53819
53820         if (locator) {
53821             background.toggleOverlayLayer(locator);
53822         }
53823
53824         var overlays = (q.overlays || '').split(',');
53825         overlays.forEach(function(overlay) {
53826             overlay = findSource(overlay);
53827             if (overlay) {
53828                 background.toggleOverlayLayer(overlay);
53829             }
53830         });
53831
53832         if (q.gpx) {
53833             var gpx = context.layers().layer('gpx');
53834             if (gpx) {
53835                 gpx.url(q.gpx);
53836             }
53837         }
53838
53839         if (q.offset) {
53840             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
53841                 return !isNaN(n) && n;
53842             });
53843
53844             if (offset.length === 2) {
53845                 background.offset(geoMetersToOffset(offset));
53846             }
53847         }
53848     };
53849
53850
53851     return utilRebind(background, dispatch$$1, 'on');
53852 }
53853
53854 function rendererFeatures(context) {
53855     var traffic_roads = {
53856         'motorway': true,
53857         'motorway_link': true,
53858         'trunk': true,
53859         'trunk_link': true,
53860         'primary': true,
53861         'primary_link': true,
53862         'secondary': true,
53863         'secondary_link': true,
53864         'tertiary': true,
53865         'tertiary_link': true,
53866         'residential': true,
53867         'unclassified': true,
53868         'living_street': true
53869     };
53870
53871     var service_roads = {
53872         'service': true,
53873         'road': true,
53874         'track': true
53875     };
53876
53877     var paths = {
53878         'path': true,
53879         'footway': true,
53880         'cycleway': true,
53881         'bridleway': true,
53882         'steps': true,
53883         'pedestrian': true,
53884         'corridor': true
53885     };
53886
53887     var past_futures = {
53888         'proposed': true,
53889         'construction': true,
53890         'abandoned': true,
53891         'dismantled': true,
53892         'disused': true,
53893         'razed': true,
53894         'demolished': true,
53895         'obliterated': true
53896     };
53897
53898     var dispatch$$1 = dispatch('change', 'redraw'),
53899         _cullFactor = 1,
53900         _cache = {},
53901         _features = {},
53902         _stats = {},
53903         _keys = [],
53904         _hidden = [];
53905
53906
53907     function update() {
53908         _hidden = features.hidden();
53909         dispatch$$1.call('change');
53910         dispatch$$1.call('redraw');
53911     }
53912
53913
53914     function defineFeature(k, filter, max$$1) {
53915         _keys.push(k);
53916         _features[k] = {
53917             filter: filter,
53918             enabled: true,   // whether the user wants it enabled..
53919             count: 0,
53920             currentMax: (max$$1 || Infinity),
53921             defaultMax: (max$$1 || Infinity),
53922             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
53923             disable: function() { this.enabled = false; this.currentMax = 0; },
53924             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
53925             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
53926         };
53927     }
53928
53929
53930     defineFeature('points', function isPoint(entity, resolver, geometry) {
53931         return geometry === 'point';
53932     }, 200);
53933
53934     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53935         return traffic_roads[entity.tags.highway];
53936     });
53937
53938     defineFeature('service_roads', function isServiceRoad(entity) {
53939         return service_roads[entity.tags.highway];
53940     });
53941
53942     defineFeature('paths', function isPath(entity) {
53943         return paths[entity.tags.highway];
53944     });
53945
53946     defineFeature('buildings', function isBuilding(entity) {
53947         return (
53948             !!entity.tags['building:part'] ||
53949             (!!entity.tags.building && entity.tags.building !== 'no') ||
53950             entity.tags.amenity === 'shelter' ||
53951             entity.tags.parking === 'multi-storey' ||
53952             entity.tags.parking === 'sheds' ||
53953             entity.tags.parking === 'carports' ||
53954             entity.tags.parking === 'garage_boxes'
53955         );
53956     }, 250);
53957
53958     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
53959         return geometry === 'area' &&
53960             !_features.buildings.filter(entity) &&
53961             !_features.water.filter(entity);
53962     });
53963
53964     defineFeature('boundaries', function isBoundary(entity) {
53965         return !!entity.tags.boundary;
53966     });
53967
53968     defineFeature('water', function isWater(entity) {
53969         return (
53970             !!entity.tags.waterway ||
53971             entity.tags.natural === 'water' ||
53972             entity.tags.natural === 'coastline' ||
53973             entity.tags.natural === 'bay' ||
53974             entity.tags.landuse === 'pond' ||
53975             entity.tags.landuse === 'basin' ||
53976             entity.tags.landuse === 'reservoir' ||
53977             entity.tags.landuse === 'salt_pond'
53978         );
53979     });
53980
53981     defineFeature('rail', function isRail(entity) {
53982         return (
53983             !!entity.tags.railway ||
53984             entity.tags.landuse === 'railway'
53985         ) && !(
53986             traffic_roads[entity.tags.highway] ||
53987             service_roads[entity.tags.highway] ||
53988             paths[entity.tags.highway]
53989         );
53990     });
53991
53992     defineFeature('power', function isPower(entity) {
53993         return !!entity.tags.power;
53994     });
53995
53996     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
53997     defineFeature('past_future', function isPastFuture(entity) {
53998         if (
53999             traffic_roads[entity.tags.highway] ||
54000             service_roads[entity.tags.highway] ||
54001             paths[entity.tags.highway]
54002         ) { return false; }
54003
54004         var strings = Object.keys(entity.tags);
54005
54006         for (var i = 0; i < strings.length; i++) {
54007             var s = strings[i];
54008             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
54009         }
54010         return false;
54011     });
54012
54013     // Lines or areas that don't match another feature filter.
54014     // IMPORTANT: The 'others' feature must be the last one defined,
54015     //   so that code in getMatches can skip this test if `hasMatch = true`
54016     defineFeature('others', function isOther(entity, resolver, geometry) {
54017         return (geometry === 'line' || geometry === 'area');
54018     });
54019
54020
54021     function features() {}
54022
54023
54024     features.features = function() {
54025         return _features;
54026     };
54027
54028
54029     features.keys = function() {
54030         return _keys;
54031     };
54032
54033
54034     features.enabled = function(k) {
54035         if (!arguments.length) {
54036             return _keys.filter(function(k) { return _features[k].enabled; });
54037         }
54038         return _features[k] && _features[k].enabled;
54039     };
54040
54041
54042     features.disabled = function(k) {
54043         if (!arguments.length) {
54044             return _keys.filter(function(k) { return !_features[k].enabled; });
54045         }
54046         return _features[k] && !_features[k].enabled;
54047     };
54048
54049
54050     features.hidden = function(k) {
54051         if (!arguments.length) {
54052             return _keys.filter(function(k) { return _features[k].hidden(); });
54053         }
54054         return _features[k] && _features[k].hidden();
54055     };
54056
54057
54058     features.autoHidden = function(k) {
54059         if (!arguments.length) {
54060             return _keys.filter(function(k) { return _features[k].autoHidden(); });
54061         }
54062         return _features[k] && _features[k].autoHidden();
54063     };
54064
54065
54066     features.enable = function(k) {
54067         if (_features[k] && !_features[k].enabled) {
54068             _features[k].enable();
54069             update();
54070         }
54071     };
54072
54073
54074     features.disable = function(k) {
54075         if (_features[k] && _features[k].enabled) {
54076             _features[k].disable();
54077             update();
54078         }
54079     };
54080
54081
54082     features.toggle = function(k) {
54083         if (_features[k]) {
54084             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
54085             update();
54086         }
54087     };
54088
54089
54090     features.resetStats = function() {
54091         for (var i = 0; i < _keys.length; i++) {
54092             _features[_keys[i]].count = 0;
54093         }
54094         dispatch$$1.call('change');
54095     };
54096
54097
54098     features.gatherStats = function(d, resolver, dimensions) {
54099         var needsRedraw = false,
54100             type = lodash.groupBy(d, function(ent) { return ent.type; }),
54101             entities = [].concat(type.relation || [], type.way || [], type.node || []),
54102             currHidden, geometry, matches, i, j;
54103
54104         for (i = 0; i < _keys.length; i++) {
54105             _features[_keys[i]].count = 0;
54106         }
54107
54108         // adjust the threshold for point/building culling based on viewport size..
54109         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
54110         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
54111
54112         for (i = 0; i < entities.length; i++) {
54113             geometry = entities[i].geometry(resolver);
54114             if (!(geometry === 'vertex' || geometry === 'relation')) {
54115                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
54116                 for (j = 0; j < matches.length; j++) {
54117                     _features[matches[j]].count++;
54118                 }
54119             }
54120         }
54121
54122         currHidden = features.hidden();
54123         if (currHidden !== _hidden) {
54124             _hidden = currHidden;
54125             needsRedraw = true;
54126             dispatch$$1.call('change');
54127         }
54128
54129         return needsRedraw;
54130     };
54131
54132
54133     features.stats = function() {
54134         for (var i = 0; i < _keys.length; i++) {
54135             _stats[_keys[i]] = _features[_keys[i]].count;
54136         }
54137
54138         return _stats;
54139     };
54140
54141
54142     features.clear = function(d) {
54143         for (var i = 0; i < d.length; i++) {
54144             features.clearEntity(d[i]);
54145         }
54146     };
54147
54148
54149     features.clearEntity = function(entity) {
54150         delete _cache[osmEntity$$1.key(entity)];
54151     };
54152
54153
54154     features.reset = function() {
54155         _cache = {};
54156     };
54157
54158
54159     features.getMatches = function(entity, resolver, geometry) {
54160         if (geometry === 'vertex' || geometry === 'relation') return {};
54161
54162         var ent = osmEntity$$1.key(entity);
54163         if (!_cache[ent]) {
54164             _cache[ent] = {};
54165         }
54166
54167         if (!_cache[ent].matches) {
54168             var matches = {},
54169                 hasMatch = false;
54170
54171             for (var i = 0; i < _keys.length; i++) {
54172                 if (_keys[i] === 'others') {
54173                     if (hasMatch) continue;
54174
54175                     // Multipolygon members:
54176                     // If an entity...
54177                     //   1. is a way that hasn't matched other 'interesting' feature rules,
54178                     //   2. and it belongs to a single parent multipolygon relation
54179                     // ...then match whatever feature rules the parent multipolygon has matched.
54180                     // see #2548, #2887
54181                     //
54182                     // IMPORTANT:
54183                     // For this to work, getMatches must be called on relations before ways.
54184                     //
54185                     if (entity.type === 'way') {
54186                         var parents = features.getParents(entity, resolver, geometry);
54187                         if (parents.length === 1 && parents[0].isMultipolygon()) {
54188                             var pkey = osmEntity$$1.key(parents[0]);
54189                             if (_cache[pkey] && _cache[pkey].matches) {
54190                                 matches = lodash.clone(_cache[pkey].matches);
54191                                 continue;
54192                             }
54193                         }
54194                     }
54195                 }
54196
54197                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
54198                     matches[_keys[i]] = hasMatch = true;
54199                 }
54200             }
54201             _cache[ent].matches = matches;
54202         }
54203
54204         return _cache[ent].matches;
54205     };
54206
54207
54208     features.getParents = function(entity, resolver, geometry) {
54209         if (geometry === 'point') return [];
54210
54211         var ent = osmEntity$$1.key(entity);
54212         if (!_cache[ent]) {
54213             _cache[ent] = {};
54214         }
54215
54216         if (!_cache[ent].parents) {
54217             var parents = [];
54218             if (geometry === 'vertex') {
54219                 parents = resolver.parentWays(entity);
54220             } else {   // 'line', 'area', 'relation'
54221                 parents = resolver.parentRelations(entity);
54222             }
54223             _cache[ent].parents = parents;
54224         }
54225         return _cache[ent].parents;
54226     };
54227
54228
54229     features.isHiddenFeature = function(entity, resolver, geometry) {
54230         if (!_hidden.length) return false;
54231         if (!entity.version) return false;
54232
54233         var matches = features.getMatches(entity, resolver, geometry);
54234
54235         for (var i = 0; i < _hidden.length; i++) {
54236             if (matches[_hidden[i]]) return true;
54237         }
54238         return false;
54239     };
54240
54241
54242     features.isHiddenChild = function(entity, resolver, geometry) {
54243         if (!_hidden.length) return false;
54244         if (!entity.version || geometry === 'point') return false;
54245
54246         var parents = features.getParents(entity, resolver, geometry);
54247         if (!parents.length) return false;
54248
54249         for (var i = 0; i < parents.length; i++) {
54250             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
54251                 return false;
54252             }
54253         }
54254         return true;
54255     };
54256
54257
54258     features.hasHiddenConnections = function(entity, resolver) {
54259         if (!_hidden.length) return false;
54260         var childNodes, connections;
54261
54262         if (entity.type === 'midpoint') {
54263             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
54264             connections = [];
54265         } else {
54266             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
54267             connections = features.getParents(entity, resolver, entity.geometry(resolver));
54268         }
54269
54270         // gather ways connected to child nodes..
54271         connections = lodash.reduce(childNodes, function(result, e) {
54272             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
54273         }, connections);
54274
54275         return connections.length ? lodash.some(connections, function(e) {
54276             return features.isHidden(e, resolver, e.geometry(resolver));
54277         }) : false;
54278     };
54279
54280
54281     features.isHidden = function(entity, resolver, geometry) {
54282         if (!_hidden.length) return false;
54283         if (!entity.version) return false;
54284
54285         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
54286         return fn(entity, resolver, geometry);
54287     };
54288
54289
54290     features.filter = function(d, resolver) {
54291         if (!_hidden.length) return d;
54292
54293         var result = [];
54294         for (var i = 0; i < d.length; i++) {
54295             var entity = d[i];
54296             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
54297                 result.push(entity);
54298             }
54299         }
54300         return result;
54301     };
54302
54303
54304     return utilRebind(features, dispatch$$1, 'on');
54305 }
54306
54307 function utilBindOnce(target, type, listener, capture) {
54308     var typeOnce = type + '.once';
54309     function one() {
54310         target.on(typeOnce, null);
54311         listener.apply(this, arguments);
54312     }
54313     target.on(typeOnce, one, capture);
54314     return this;
54315 }
54316
54317 function rendererMap(context) {
54318
54319     var dimensions = [1, 1],
54320         dispatch$$1 = dispatch('move', 'drawn'),
54321         projection = context.projection,
54322         dblclickEnabled = true,
54323         redrawEnabled = true,
54324         transformStart = projection.transform(),
54325         transformed = false,
54326         minzoom = 0,
54327         drawLayers = svgLayers(projection, context),
54328         drawPoints = svgPoints$$1(projection, context),
54329         drawVertices = svgVertices$$1(projection, context),
54330         drawLines = svgLines$$1(projection),
54331         drawAreas = svgAreas$$1(projection, context),
54332         drawMidpoints = svgMidpoints$$1(projection, context),
54333         drawLabels = svgLabels(projection, context),
54334         supersurface = select(null),
54335         wrapper = select(null),
54336         surface = select(null),
54337         mouse$$1,
54338         mousemove;
54339
54340     var zoom$$1 = zoom$1()
54341             .scaleExtent([ztok(2), ztok(24)])
54342             .interpolate(value$1)
54343             .filter(zoomEventFilter)
54344             .on('zoom', zoomPan);
54345
54346     var _selection = select(null);
54347
54348
54349     function map$$1(selection$$1) {
54350
54351         _selection = selection$$1;
54352
54353         context
54354             .on('change.map', immediateRedraw);
54355
54356         context.connection()
54357             .on('change.map', immediateRedraw);
54358
54359         context.history()
54360             .on('change.map', immediateRedraw)
54361             .on('undone.context redone.context', function(stack$$1) {
54362                 var followSelected = false;
54363                 if (Array.isArray(stack$$1.selectedIDs)) {
54364                     followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
54365                     context.enter(
54366                         modeSelect(context, stack$$1.selectedIDs).suppressMenu(true).follow(followSelected)
54367                     );
54368                 }
54369                 if (!followSelected && stack$$1.transform) {
54370                     map$$1.transformEase(stack$$1.transform);
54371                 }
54372             });
54373
54374         context.background()
54375             .on('change.map', immediateRedraw);
54376
54377         context.features()
54378             .on('redraw.map', immediateRedraw);
54379
54380         drawLayers
54381             .on('change.map', function() {
54382                 context.background().updateImagery();
54383                 immediateRedraw();
54384             });
54385
54386         selection$$1
54387             .on('dblclick.map', dblClick)
54388             .call(zoom$$1)
54389             .call(zoom$$1.transform, projection.transform());
54390
54391         supersurface = selection$$1.append('div')
54392             .attr('id', 'supersurface')
54393             .call(utilSetTransform, 0, 0);
54394
54395         // Need a wrapper div because Opera can't cope with an absolutely positioned
54396         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
54397         wrapper = supersurface
54398             .append('div')
54399             .attr('class', 'layer layer-data');
54400
54401         map$$1.surface = surface = wrapper
54402             .call(drawLayers)
54403             .selectAll('.surface')
54404             .attr('id', 'surface');
54405
54406         surface
54407             .call(drawLabels.observe)
54408             .on('mousedown.zoom', function() {
54409                 if (event.button === 2) {
54410                     event.stopPropagation();
54411                 }
54412             }, true)
54413             .on('mouseup.zoom', function() {
54414                 if (resetTransform()) immediateRedraw();
54415             })
54416             .on('mousemove.map', function() {
54417                 mousemove = event;
54418             })
54419             .on('mouseover.vertices', function() {
54420                 if (map$$1.editable() && !transformed) {
54421                     var hover = event.target.__data__;
54422                     surface.selectAll('.data-layer-osm')
54423                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54424                     dispatch$$1.call('drawn', this, {full: false});
54425                 }
54426             })
54427             .on('mouseout.vertices', function() {
54428                 if (map$$1.editable() && !transformed) {
54429                     var hover = event.relatedTarget && event.relatedTarget.__data__;
54430                     surface.selectAll('.data-layer-osm')
54431                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
54432                     dispatch$$1.call('drawn', this, {full: false});
54433                 }
54434             });
54435
54436         supersurface
54437             .call(context.background());
54438
54439         context.on('enter.map', function() {
54440             if (map$$1.editable() && !transformed) {
54441                 var all = context.intersects(map$$1.extent()),
54442                     filter = utilFunctor(true),
54443                     graph = context.graph();
54444
54445                 all = context.features().filter(all, graph);
54446                 surface.selectAll('.data-layer-osm')
54447                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
54448                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
54449                 dispatch$$1.call('drawn', this, {full: false});
54450             }
54451         });
54452
54453         map$$1.dimensions(utilGetDimensions(selection$$1));
54454     }
54455
54456
54457     function zoomEventFilter() {
54458         // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
54459         // Intercept `mousedown` and check if there is an orphaned zoom gesture.
54460         // This can happen if a previous `mousedown` occurred without a `mouseup`.
54461         // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
54462         // so that d3-zoom won't stop propagation of new `mousedown` events.
54463         if (event.type === 'mousedown') {
54464             var hasOrphan = false;
54465             var listeners = window.__on;
54466             for (var i = 0; i < listeners.length; i++) {
54467                 var listener = listeners[i];
54468                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
54469                     hasOrphan = true;
54470                     break;
54471                 }
54472             }
54473             if (hasOrphan) {
54474                 var event$$1 = window.CustomEvent;
54475                 if (event$$1) {
54476                     event$$1 = new event$$1('mouseup');
54477                 } else {
54478                     event$$1 = window.document.createEvent('Event');
54479                     event$$1.initEvent('mouseup', false, false);
54480                 }
54481                 // Event needs to be dispatched with an event.view property.
54482                 event$$1.view = window;
54483                 window.dispatchEvent(event$$1);
54484             }
54485         }
54486
54487         return event.button !== 2;   // ignore right clicks
54488     }
54489
54490
54491     function ztok(z) {
54492         return 256 * Math.pow(2, z);
54493     }
54494
54495     function ktoz(k) {
54496         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
54497     }
54498
54499     function pxCenter() {
54500         return [dimensions[0] / 2, dimensions[1] / 2];
54501     }
54502
54503
54504     function drawVector(difference, extent$$1) {
54505         var graph = context.graph(),
54506             features = context.features(),
54507             all = context.intersects(map$$1.extent()),
54508             data, filter;
54509
54510         if (difference) {
54511             var complete = difference.complete(map$$1.extent());
54512             data = lodash.compact(lodash.values(complete));
54513             filter = function(d) { return d.id in complete; };
54514             features.clear(data);
54515
54516         } else {
54517             // force a full redraw if gatherStats detects that a feature
54518             // should be auto-hidden (e.g. points or buildings)..
54519             if (features.gatherStats(all, graph, dimensions)) {
54520                 extent$$1 = undefined;
54521             }
54522
54523             if (extent$$1) {
54524                 data = context.intersects(map$$1.extent().intersection(extent$$1));
54525                 var set$$1 = set$2(lodash.map(data, 'id'));
54526                 filter = function(d) { return set$$1.has(d.id); };
54527
54528             } else {
54529                 data = all;
54530                 filter = utilFunctor(true);
54531             }
54532         }
54533
54534         data = features.filter(data, graph);
54535
54536         surface.selectAll('.data-layer-osm')
54537             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
54538             .call(drawLines, graph, data, filter)
54539             .call(drawAreas, graph, data, filter)
54540             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
54541             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
54542             .call(drawPoints, graph, data, filter);
54543
54544         dispatch$$1.call('drawn', this, {full: true});
54545     }
54546
54547
54548     function editOff() {
54549         context.features().resetStats();
54550         surface.selectAll('.layer-osm *').remove();
54551         dispatch$$1.call('drawn', this, {full: true});
54552     }
54553
54554
54555     function dblClick() {
54556         if (!dblclickEnabled) {
54557             event.preventDefault();
54558             event.stopImmediatePropagation();
54559         }
54560     }
54561
54562
54563     function zoomPan(manualEvent) {
54564         var eventTransform = (manualEvent || event).transform;
54565
54566         if (transformStart.x === eventTransform.x &&
54567             transformStart.y === eventTransform.y &&
54568             transformStart.k === eventTransform.k) {
54569             return;  // no change
54570         }
54571
54572         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
54573             surface.interrupt();
54574             uiFlash(context.container())
54575                 .select('.content')
54576                 .text(t('cannot_zoom'));
54577             setZoom(context.minEditableZoom(), true);
54578             queueRedraw();
54579             dispatch$$1.call('move', this, map$$1);
54580             return;
54581         }
54582
54583         projection.transform(eventTransform);
54584
54585         var scale = eventTransform.k / transformStart.k,
54586             tX = (eventTransform.x / scale - transformStart.x) * scale,
54587             tY = (eventTransform.y / scale - transformStart.y) * scale;
54588
54589         transformed = true;
54590         utilSetTransform(supersurface, tX, tY, scale);
54591         queueRedraw();
54592
54593         dispatch$$1.call('move', this, map$$1);
54594     }
54595
54596
54597     function resetTransform() {
54598         if (!transformed) return false;
54599
54600         surface.selectAll('.radial-menu').interrupt().remove();
54601         utilSetTransform(supersurface, 0, 0);
54602         transformed = false;
54603         return true;
54604     }
54605
54606
54607     function redraw(difference, extent$$1) {
54608         if (surface.empty() || !redrawEnabled) return;
54609
54610         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
54611         // It would result in artifacts where differenced entities are redrawn with
54612         // one transform and unchanged entities with another.
54613         if (resetTransform()) {
54614             difference = extent$$1 = undefined;
54615         }
54616
54617         var z = String(~~map$$1.zoom());
54618         if (surface.attr('data-zoom') !== z) {
54619             surface.attr('data-zoom', z)
54620                 .classed('low-zoom', z <= 16);
54621         }
54622
54623         if (!difference) {
54624             supersurface.call(context.background());
54625         }
54626
54627         wrapper
54628             .call(drawLayers);
54629
54630         // OSM
54631         if (map$$1.editable()) {
54632             context.loadTiles(projection, dimensions);
54633             drawVector(difference, extent$$1);
54634         } else {
54635             editOff();
54636         }
54637
54638         transformStart = projection.transform();
54639
54640         return map$$1;
54641     }
54642
54643
54644     var queueRedraw = lodash.throttle(redraw, 750);
54645
54646
54647     var immediateRedraw = function(difference, extent$$1) {
54648         if (!difference && !extent$$1) queueRedraw.cancel();
54649         redraw(difference, extent$$1);
54650     };
54651
54652
54653     function pointLocation(p) {
54654         var translate = projection.translate(),
54655             scale = projection.scale() * 2 * Math.PI;
54656         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
54657     }
54658
54659
54660     function locationPoint(l) {
54661         var translate = projection.translate(),
54662             scale = projection.scale() * 2 * Math.PI;
54663         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
54664     }
54665
54666
54667     map$$1.mouse = function() {
54668         var event$$1 = mousemove || event;
54669         if (event$$1) {
54670             var s;
54671             while ((s = event$$1.sourceEvent)) { event$$1 = s; }
54672             return mouse$$1(event$$1);
54673         }
54674         return null;
54675     };
54676
54677
54678     map$$1.mouseCoordinates = function() {
54679         return projection.invert(map$$1.mouse());
54680     };
54681
54682
54683     map$$1.dblclickEnable = function(_) {
54684         if (!arguments.length) return dblclickEnabled;
54685         dblclickEnabled = _;
54686         return map$$1;
54687     };
54688
54689
54690     map$$1.redrawEnable = function(_) {
54691         if (!arguments.length) return redrawEnabled;
54692         redrawEnabled = _;
54693         return map$$1;
54694     };
54695
54696
54697     function setTransform(t2, duration, force) {
54698         var t$$1 = projection.transform();
54699         if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
54700             return false;
54701         }
54702
54703         if (duration) {
54704             _selection
54705                 .transition()
54706                 .duration(duration)
54707                 .on('start', function() { map$$1.startEase(); })
54708                 .call(zoom$$1.transform, identity$9.translate(t2.x, t2.y).scale(t2.k));
54709         } else {
54710             projection.transform(t2);
54711             transformStart = t2;
54712             _selection.call(zoom$$1.transform, transformStart);
54713         }
54714     }
54715
54716
54717     function setZoom(z2, force, duration) {
54718         if (z2 === map$$1.zoom() && !force) {
54719             return false;
54720         }
54721
54722         var k = projection.scale(),
54723             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
54724             center = pxCenter(),
54725             l = pointLocation(center);
54726
54727         projection.scale(k2);
54728
54729         var t$$1 = projection.translate();
54730         l = locationPoint(l);
54731
54732         t$$1[0] += center[0] - l[0];
54733         t$$1[1] += center[1] - l[1];
54734
54735         if (duration) {
54736             projection.scale(k);  // reset scale
54737             _selection
54738                 .transition()
54739                 .duration(duration)
54740                 .on('start', function() { map$$1.startEase(); })
54741                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k2));
54742         } else {
54743             projection.translate(t$$1);
54744             transformStart = projection.transform();
54745             _selection.call(zoom$$1.transform, transformStart);
54746         }
54747
54748         return true;
54749     }
54750
54751
54752     function setCenter(loc2, duration) {
54753         var c = map$$1.center();
54754         if (loc2[0] === c[0] && loc2[1] === c[1]) {
54755             return false;
54756         }
54757
54758         var t$$1 = projection.translate(),
54759             k = projection.scale(),
54760             pxC = pxCenter(),
54761             ll = projection(loc2);
54762
54763         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
54764         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
54765
54766         if (duration) {
54767             _selection
54768                 .transition()
54769                 .duration(duration)
54770                 .on('start', function() { map$$1.startEase(); })
54771                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54772         } else {
54773             projection.translate(t$$1);
54774             transformStart = projection.transform();
54775             _selection.call(zoom$$1.transform, transformStart);
54776         }
54777
54778         return true;
54779     }
54780
54781
54782     map$$1.pan = function(delta, duration) {
54783         var t$$1 = projection.translate(),
54784             k = projection.scale();
54785
54786         t$$1[0] += delta[0];
54787         t$$1[1] += delta[1];
54788
54789         if (duration) {
54790             _selection
54791                 .transition()
54792                 .duration(duration)
54793                 .on('start', function() { map$$1.startEase(); })
54794                 .call(zoom$$1.transform, identity$9.translate(t$$1[0], t$$1[1]).scale(k));
54795         } else {
54796             projection.translate(t$$1);
54797             transformStart = projection.transform();
54798             _selection.call(zoom$$1.transform, transformStart);
54799             dispatch$$1.call('move', this, map$$1);
54800             immediateRedraw();
54801         }
54802
54803         return map$$1;
54804     };
54805
54806
54807     map$$1.dimensions = function(_) {
54808         if (!arguments.length) return dimensions;
54809         var center = map$$1.center();
54810         dimensions = _;
54811         drawLayers.dimensions(dimensions);
54812         context.background().dimensions(dimensions);
54813         projection.clipExtent([[0, 0], dimensions]);
54814         mouse$$1 = utilFastMouse(supersurface.node());
54815         setCenter(center);
54816
54817         queueRedraw();
54818         return map$$1;
54819     };
54820
54821
54822     function zoomIn(delta) {
54823         setZoom(~~map$$1.zoom() + delta, true, 250);
54824     }
54825
54826     function zoomOut(delta) {
54827         setZoom(~~map$$1.zoom() - delta, true, 250);
54828     }
54829
54830     map$$1.zoomIn = function() { zoomIn(1); };
54831     map$$1.zoomInFurther = function() { zoomIn(4); };
54832
54833     map$$1.zoomOut = function() { zoomOut(1); };
54834     map$$1.zoomOutFurther = function() { zoomOut(4); };
54835
54836
54837     map$$1.center = function(loc2) {
54838         if (!arguments.length) {
54839             return projection.invert(pxCenter());
54840         }
54841
54842         if (setCenter(loc2)) {
54843             dispatch$$1.call('move', this, map$$1);
54844         }
54845
54846         queueRedraw();
54847         return map$$1;
54848     };
54849
54850
54851     map$$1.zoom = function(z2) {
54852         if (!arguments.length) {
54853             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
54854         }
54855
54856         if (z2 < minzoom) {
54857             surface.interrupt();
54858             uiFlash(context.container())
54859                 .select('.content')
54860                 .text(t('cannot_zoom'));
54861             z2 = context.minEditableZoom();
54862         }
54863
54864         if (setZoom(z2)) {
54865             dispatch$$1.call('move', this, map$$1);
54866         }
54867
54868         queueRedraw();
54869         return map$$1;
54870     };
54871
54872
54873     map$$1.zoomTo = function(entity, zoomLimits) {
54874         var extent$$1 = entity.extent(context.graph());
54875         if (!isFinite(extent$$1.area())) return;
54876
54877         var z2 = map$$1.trimmedExtentZoom(extent$$1);
54878         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
54879         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
54880     };
54881
54882
54883     map$$1.centerZoom = function(loc2, z2) {
54884         var centered = setCenter(loc2),
54885             zoomed   = setZoom(z2);
54886
54887         if (centered || zoomed) {
54888             dispatch$$1.call('move', this, map$$1);
54889         }
54890
54891         queueRedraw();
54892         return map$$1;
54893     };
54894
54895
54896     map$$1.centerEase = function(loc2, duration) {
54897         duration = duration || 250;
54898         setCenter(loc2, duration);
54899         return map$$1;
54900     };
54901
54902
54903     map$$1.zoomEase = function(z2, duration) {
54904         duration = duration || 250;
54905         setZoom(z2, false, duration);
54906         return map$$1;
54907     };
54908
54909
54910     map$$1.transformEase = function(t2, duration) {
54911         duration = duration || 250;
54912         setTransform(t2, duration, false);
54913         return map$$1;
54914     };
54915
54916
54917     map$$1.startEase = function() {
54918         utilBindOnce(surface, 'mousedown.ease', function() {
54919             map$$1.cancelEase();
54920         });
54921         return map$$1;
54922     };
54923
54924
54925     map$$1.cancelEase = function() {
54926         _selection.interrupt();
54927         return map$$1;
54928     };
54929
54930
54931     map$$1.extent = function(_) {
54932         if (!arguments.length) {
54933             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
54934                                  projection.invert([dimensions[0], 0]));
54935         } else {
54936             var extent$$1 = geoExtent$$1(_);
54937             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
54938         }
54939     };
54940
54941
54942     map$$1.trimmedExtent = function(_) {
54943         if (!arguments.length) {
54944             var headerY = 60, footerY = 30, pad = 10;
54945             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
54946                                  projection.invert([dimensions[0] - pad, headerY + pad]));
54947         } else {
54948             var extent$$1 = geoExtent$$1(_);
54949             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
54950         }
54951     };
54952
54953
54954     function calcZoom(extent$$1, dim) {
54955         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
54956             br = projection([extent$$1[1][0], extent$$1[0][1]]);
54957
54958         // Calculate maximum zoom that fits extent
54959         var hFactor = (br[0] - tl[0]) / dim[0],
54960             vFactor = (br[1] - tl[1]) / dim[1],
54961             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
54962             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
54963             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
54964
54965         return newZoom;
54966     }
54967
54968
54969     map$$1.extentZoom = function(_) {
54970         return calcZoom(geoExtent$$1(_), dimensions);
54971     };
54972
54973
54974     map$$1.trimmedExtentZoom = function(_) {
54975         var trimY = 120, trimX = 40,
54976             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
54977         return calcZoom(geoExtent$$1(_), trimmed);
54978     };
54979
54980
54981     map$$1.editable = function() {
54982         return map$$1.zoom() >= context.minEditableZoom();
54983     };
54984
54985
54986     map$$1.minzoom = function(_) {
54987         if (!arguments.length) return minzoom;
54988         minzoom = _;
54989         return map$$1;
54990     };
54991
54992
54993     map$$1.layers = drawLayers;
54994
54995
54996     return utilRebind(map$$1, dispatch$$1, 'on');
54997 }
54998
54999 var TAU = 2 * Math.PI;
55000 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
55001 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
55002 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
55003 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
55004
55005
55006 function uiMapInMap(context) {
55007     var key = '/';
55008
55009
55010     function map_in_map(selection$$1) {
55011         var backgroundLayer = rendererTileLayer(context),
55012             overlayLayers = {},
55013             projection = geoRawMercator(),
55014             gpxLayer = svgGpx(projection, context).showLabels(false),
55015             debugLayer = svgDebug(projection, context),
55016             zoom$$1 = zoom$1()
55017                 .scaleExtent([ztok(0.5), ztok(24)])
55018                 .on('start', zoomStarted)
55019                 .on('zoom', zoomed)
55020                 .on('end', zoomEnded),
55021             isTransformed = false,
55022             isHidden = true,
55023             skipEvents = false,
55024             gesture = null,
55025             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
55026             wrap = select(null),
55027             tiles = select(null),
55028             viewport = select(null),
55029             tStart,  // transform at start of gesture
55030             tCurr,   // transform at most recent event
55031             timeoutId;
55032
55033
55034         function zoomStarted() {
55035             if (skipEvents) return;
55036             tStart = tCurr = projection.transform();
55037             gesture = null;
55038         }
55039
55040
55041         function zoomed() {
55042             if (skipEvents) return;
55043
55044             var x = event.transform.x,
55045                 y = event.transform.y,
55046                 k = event.transform.k,
55047                 isZooming = (k !== tStart.k),
55048                 isPanning = (x !== tStart.x || y !== tStart.y);
55049
55050             if (!isZooming && !isPanning) {
55051                 return;  // no change
55052             }
55053
55054             // lock in either zooming or panning, don't allow both in minimap.
55055             if (!gesture) {
55056                 gesture = isZooming ? 'zoom' : 'pan';
55057             }
55058
55059             var tMini = projection.transform(),
55060                 tX, tY, scale;
55061
55062             if (gesture === 'zoom') {
55063                 var dMini = utilGetDimensions(wrap),
55064                     cMini = vecScale(dMini, 0.5);
55065                 scale = k / tMini.k;
55066                 tX = (cMini[0] / scale - cMini[0]) * scale;
55067                 tY = (cMini[1] / scale - cMini[1]) * scale;
55068             } else {
55069                 k = tMini.k;
55070                 scale = 1;
55071                 tX = x - tMini.x;
55072                 tY = y - tMini.y;
55073             }
55074
55075             utilSetTransform(tiles, tX, tY, scale);
55076             utilSetTransform(viewport, 0, 0, scale);
55077             isTransformed = true;
55078             tCurr = identity$9.translate(x, y).scale(k);
55079
55080             var zMain = ktoz(context.projection.scale()),
55081                 zMini = ktoz(k);
55082
55083             zDiff = zMain - zMini;
55084
55085             queueRedraw();
55086         }
55087
55088
55089         function zoomEnded() {
55090             if (skipEvents) return;
55091             if (gesture !== 'pan') return;
55092
55093             updateProjection();
55094             gesture = null;
55095             var dMini = utilGetDimensions(wrap),
55096                 cMini = vecScale(dMini, 0.5);
55097             context.map().center(projection.invert(cMini));   // recenter main map..
55098         }
55099
55100
55101         function updateProjection() {
55102             var loc = context.map().center(),
55103                 dMini = utilGetDimensions(wrap),
55104                 cMini = vecScale(dMini, 0.5),
55105                 tMain = context.projection.transform(),
55106                 zMain = ktoz(tMain.k),
55107                 zMini = Math.max(zMain - zDiff, 0.5),
55108                 kMini = ztok(zMini);
55109
55110             projection
55111                 .translate([tMain.x, tMain.y])
55112                 .scale(kMini);
55113
55114             var point = projection(loc),
55115                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
55116                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
55117                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
55118
55119             projection
55120                 .translate([xMini, yMini])
55121                 .clipExtent([[0, 0], dMini]);
55122
55123             tCurr = projection.transform();
55124
55125             if (isTransformed) {
55126                 utilSetTransform(tiles, 0, 0);
55127                 utilSetTransform(viewport, 0, 0);
55128                 isTransformed = false;
55129             }
55130
55131             zoom$$1
55132                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
55133
55134             skipEvents = true;
55135             wrap.call(zoom$$1.transform, tCurr);
55136             skipEvents = false;
55137         }
55138
55139
55140         function redraw() {
55141             clearTimeout(timeoutId);
55142             if (isHidden) return;
55143
55144             updateProjection();
55145
55146             var dMini = utilGetDimensions(wrap),
55147                 zMini = ktoz(projection.scale());
55148
55149             // setup tile container
55150             tiles = wrap
55151                 .selectAll('.map-in-map-tiles')
55152                 .data([0]);
55153
55154             tiles = tiles.enter()
55155                 .append('div')
55156                 .attr('class', 'map-in-map-tiles')
55157                 .merge(tiles);
55158
55159             // redraw background
55160             backgroundLayer
55161                 .source(context.background().baseLayerSource())
55162                 .projection(projection)
55163                 .dimensions(dMini);
55164
55165             var background = tiles
55166                 .selectAll('.map-in-map-background')
55167                 .data([0]);
55168
55169             background.enter()
55170                 .append('div')
55171                 .attr('class', 'map-in-map-background')
55172                 .merge(background)
55173                 .call(backgroundLayer);
55174
55175
55176             // redraw overlay
55177             var overlaySources = context.background().overlayLayerSources();
55178             var activeOverlayLayers = [];
55179             for (var i = 0; i < overlaySources.length; i++) {
55180                 if (overlaySources[i].validZoom(zMini)) {
55181                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
55182                     activeOverlayLayers.push(overlayLayers[i]
55183                         .source(overlaySources[i])
55184                         .projection(projection)
55185                         .dimensions(dMini));
55186                 }
55187             }
55188
55189             var overlay = tiles
55190                 .selectAll('.map-in-map-overlay')
55191                 .data([0]);
55192
55193             overlay = overlay.enter()
55194                 .append('div')
55195                 .attr('class', 'map-in-map-overlay')
55196                 .merge(overlay);
55197
55198
55199             var overlays = overlay
55200                 .selectAll('div')
55201                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
55202
55203             overlays.exit()
55204                 .remove();
55205
55206             overlays = overlays.enter()
55207                 .append('div')
55208                 .merge(overlays)
55209                 .each(function(layer) { select(this).call(layer); });
55210
55211
55212             var dataLayers = tiles
55213                 .selectAll('.map-in-map-data')
55214                 .data([0]);
55215
55216             dataLayers.exit()
55217                 .remove();
55218
55219             dataLayers = dataLayers.enter()
55220                 .append('svg')
55221                 .attr('class', 'map-in-map-data')
55222                 .merge(dataLayers)
55223                 .call(gpxLayer)
55224                 .call(debugLayer);
55225
55226
55227             // redraw viewport bounding box
55228             if (gesture !== 'pan') {
55229                 var getPath = index$4(projection),
55230                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
55231
55232                 viewport = wrap.selectAll('.map-in-map-viewport')
55233                     .data([0]);
55234
55235                 viewport = viewport.enter()
55236                     .append('svg')
55237                     .attr('class', 'map-in-map-viewport')
55238                     .merge(viewport);
55239
55240
55241                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
55242                     .data([bbox]);
55243
55244                 path$$1.enter()
55245                     .append('path')
55246                     .attr('class', 'map-in-map-bbox')
55247                     .merge(path$$1)
55248                     .attr('d', getPath)
55249                     .classed('thick', function(d) { return getPath.area(d) < 30; });
55250             }
55251         }
55252
55253
55254         function queueRedraw() {
55255             clearTimeout(timeoutId);
55256             timeoutId = setTimeout(function() { redraw(); }, 750);
55257         }
55258
55259
55260         function toggle() {
55261             if (event) event.preventDefault();
55262
55263             isHidden = !isHidden;
55264
55265             var label = select('.minimap-toggle');
55266             label.classed('active', !isHidden)
55267                 .select('input').property('checked', !isHidden);
55268
55269             if (isHidden) {
55270                 wrap
55271                     .style('display', 'block')
55272                     .style('opacity', '1')
55273                     .transition()
55274                     .duration(200)
55275                     .style('opacity', '0')
55276                     .on('end', function() {
55277                         selection$$1.selectAll('.map-in-map')
55278                             .style('display', 'none');
55279                     });
55280             } else {
55281                 wrap
55282                     .style('display', 'block')
55283                     .style('opacity', '0')
55284                     .transition()
55285                     .duration(200)
55286                     .style('opacity', '1')
55287                     .on('end', function() {
55288                         redraw();
55289                     });
55290             }
55291         }
55292
55293
55294         uiMapInMap.toggle = toggle;
55295
55296         wrap = selection$$1.selectAll('.map-in-map')
55297             .data([0]);
55298
55299         wrap = wrap.enter()
55300             .append('div')
55301             .attr('class', 'map-in-map')
55302             .style('display', (isHidden ? 'none' : 'block'))
55303             .call(zoom$$1)
55304             .on('dblclick.zoom', null)
55305             .merge(wrap);
55306
55307         context.map()
55308             .on('drawn.map-in-map', function(drawn) {
55309                 if (drawn.full === true) {
55310                     redraw();
55311                 }
55312             });
55313
55314         redraw();
55315
55316         var keybinding = d3keybinding('map-in-map')
55317             .on(key, toggle);
55318
55319         select(document)
55320             .call(keybinding);
55321     }
55322
55323     return map_in_map;
55324 }
55325
55326 function uiTooltipHtml(text, key) {
55327     var s = '<span>' + text + '</span>';
55328     if (key) {
55329         s += '<div class="keyhint-wrap">' +
55330             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
55331             '<span class="keyhint"> ' + key + '</span></div>';
55332     }
55333     return s;
55334 }
55335
55336 function uiBackground(context) {
55337     var key = 'B',
55338         detected = utilDetect(),
55339         opacities = [1, 0.75, 0.5, 0.25],
55340         directions = [
55341             ['right', [0.5, 0]],
55342             ['top', [0, -0.5]],
55343             ['left', [-0.5, 0]],
55344             ['bottom', [0, 0.5]]],
55345         opacityDefault = (context.storage('background-opacity') !== null) ?
55346             (+context.storage('background-opacity')) : 1.0,
55347         customTemplate = context.storage('background-custom-template') || '',
55348         previous;
55349
55350     // Can be 0 from <1.3.0 use or due to issue #1923.
55351     if (opacityDefault === 0) opacityDefault = 1.0;
55352
55353
55354     function background(selection$$1) {
55355
55356         function sortSources(a, b) {
55357             return a.best() && !b.best() ? -1
55358                 : b.best() && !a.best() ? 1
55359                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
55360         }
55361
55362
55363         function setOpacity(d) {
55364             var bg = context.container().selectAll('.layer-background')
55365                 .transition()
55366                 .style('opacity', d)
55367                 .attr('data-opacity', d);
55368
55369             if (!detected.opera) {
55370                 utilSetTransform(bg, 0, 0);
55371             }
55372
55373             opacityList.selectAll('li')
55374                 .classed('active', function(_) { return _ === d; });
55375
55376             context.storage('background-opacity', d);
55377         }
55378
55379
55380         function setTooltips(selection$$1) {
55381             selection$$1.each(function(d, i, nodes) {
55382                 var item = select(this).select('label'),
55383                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
55384
55385                 if (d === previous) {
55386                     item.call(tooltip()
55387                         .placement(placement)
55388                         .html(true)
55389                         .title(function() {
55390                             var tip = '<div>' + t('background.switch') + '</div>';
55391                             return uiTooltipHtml(tip, uiCmd('⌘B'));
55392                         })
55393                     );
55394                 } else if (d.description) {
55395                     item.call(tooltip()
55396                         .placement(placement)
55397                         .title(d.description)
55398                     );
55399                 } else {
55400                     item.call(tooltip().destroy);
55401                 }
55402             });
55403         }
55404
55405
55406         function selectLayer() {
55407             function active$$1(d) {
55408                 return context.background().showsLayer(d);
55409             }
55410
55411             content.selectAll('.layer, .custom_layer')
55412                 .classed('active', active$$1)
55413                 .classed('switch', function(d) { return d === previous; })
55414                 .call(setTooltips)
55415                 .selectAll('input')
55416                 .property('checked', active$$1);
55417         }
55418
55419
55420         function clickSetSource(d) {
55421             event.preventDefault();
55422             previous = context.background().baseLayerSource();
55423             context.background().baseLayerSource(d);
55424             selectLayer();
55425             document.activeElement.blur();
55426         }
55427
55428
55429         function editCustom() {
55430             event.preventDefault();
55431             var template = window.prompt(t('background.custom_prompt'), customTemplate);
55432             if (template) {
55433                 setCustom(template);
55434             } else {
55435                 selectLayer();
55436             }
55437         }
55438
55439
55440         function setCustom(template) {
55441             context.storage('background-custom-template', template);
55442             var d = rendererBackgroundSource.Custom(template);
55443             content.selectAll('.custom_layer').datum(d);
55444             clickSetSource(d);
55445         }
55446
55447
55448         function clickSetOverlay(d) {
55449             event.preventDefault();
55450             context.background().toggleOverlayLayer(d);
55451             selectLayer();
55452             document.activeElement.blur();
55453         }
55454
55455
55456         function drawList(layerList, type, change, filter) {
55457             var sources = context.background()
55458                 .sources(context.map().extent())
55459                 .filter(filter);
55460
55461             var layerLinks = layerList.selectAll('li.layer')
55462                 .data(sources, function(d) { return d.name(); });
55463
55464             layerLinks.exit()
55465                 .remove();
55466
55467             var enter = layerLinks.enter()
55468                 .insert('li', '.custom_layer')
55469                 .attr('class', 'layer')
55470                 .classed('best', function(d) { return d.best(); });
55471
55472             enter.filter(function(d) { return d.best(); })
55473                 .append('div')
55474                 .attr('class', 'best')
55475                 .call(tooltip()
55476                     .title(t('background.best_imagery'))
55477                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
55478                 .append('span')
55479                 .html('&#9733;');
55480
55481             var label = enter
55482                 .append('label');
55483
55484             label
55485                 .append('input')
55486                 .attr('type', type)
55487                 .attr('name', 'layers')
55488                 .on('change', change);
55489
55490             label
55491                 .append('span')
55492                 .text(function(d) { return d.name(); });
55493
55494
55495             layerList.selectAll('li.layer')
55496                 .sort(sortSources)
55497                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
55498         }
55499
55500
55501         function update() {
55502             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
55503             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
55504
55505             selectLayer();
55506
55507             var source = context.background().baseLayerSource();
55508             if (source.id === 'custom') {
55509                 customTemplate = source.template;
55510             }
55511
55512             updateOffsetVal();
55513         }
55514
55515
55516         function updateOffsetVal() {
55517             var meters = geoOffsetToMeters(context.background().offset()),
55518                 x = +meters[0].toFixed(2),
55519                 y = +meters[1].toFixed(2);
55520
55521             selectAll('.nudge-inner-rect')
55522                 .select('input')
55523                 .classed('error', false)
55524                 .property('value', x + ', ' + y);
55525
55526             selectAll('.nudge-reset')
55527                 .classed('disabled', function() {
55528                     return (x === 0 && y === 0);
55529                 });
55530         }
55531
55532
55533         function resetOffset() {
55534             if (event.button !== 0) return;
55535             context.background().offset([0, 0]);
55536             updateOffsetVal();
55537         }
55538
55539
55540         function nudge(d) {
55541             context.background().nudge(d, context.map().zoom());
55542             updateOffsetVal();
55543         }
55544
55545
55546         function buttonOffset(d) {
55547             if (event.button !== 0) return;
55548             var timeout$$1 = window.setTimeout(function() {
55549                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
55550                 }, 500),
55551                 interval$$1;
55552
55553             function doneNudge() {
55554                 window.clearTimeout(timeout$$1);
55555                 window.clearInterval(interval$$1);
55556                 select(window)
55557                     .on('mouseup.buttonoffset', null, true)
55558                     .on('mousedown.buttonoffset', null, true);
55559             }
55560
55561             select(window)
55562                 .on('mouseup.buttonoffset', doneNudge, true)
55563                 .on('mousedown.buttonoffset', doneNudge, true);
55564
55565             nudge(d);
55566         }
55567
55568
55569         function inputOffset() {
55570             if (event.button !== 0) return;
55571             var input = select(this);
55572             var d = input.node().value;
55573
55574             if (d === '') return resetOffset();
55575
55576             d = d.replace(/;/g, ',').split(',').map(function(n) {
55577                 // if n is NaN, it will always get mapped to false.
55578                 return !isNaN(n) && n;
55579             });
55580
55581             if (d.length !== 2 || !d[0] || !d[1]) {
55582                 input.classed('error', true);
55583                 return;
55584             }
55585
55586             context.background().offset(geoMetersToOffset(d));
55587             updateOffsetVal();
55588         }
55589
55590
55591         function dragOffset() {
55592             if (event.button !== 0) return;
55593             var origin = [event.clientX, event.clientY];
55594
55595             context.container()
55596                 .append('div')
55597                 .attr('class', 'nudge-surface');
55598
55599             select(window)
55600                 .on('mousemove.offset', function() {
55601                     var latest = [event.clientX, event.clientY];
55602                     var d = [
55603                         -(origin[0] - latest[0]) / 4,
55604                         -(origin[1] - latest[1]) / 4
55605                     ];
55606
55607                     origin = latest;
55608                     nudge(d);
55609                 })
55610                 .on('mouseup.offset', function() {
55611                     if (event.button !== 0) return;
55612                     selectAll('.nudge-surface')
55613                         .remove();
55614
55615                     select(window)
55616                         .on('mousemove.offset', null)
55617                         .on('mouseup.offset', null);
55618                 });
55619
55620             event.preventDefault();
55621         }
55622
55623
55624         function hide() {
55625             setVisible(false);
55626         }
55627
55628
55629         function toggle() {
55630             if (event) event.preventDefault();
55631             tooltipBehavior.hide(button);
55632             setVisible(!button.classed('active'));
55633         }
55634
55635
55636         function quickSwitch() {
55637             if (previous) {
55638                 clickSetSource(previous);
55639             }
55640         }
55641
55642
55643         function setVisible(show) {
55644             if (show !== shown) {
55645                 button.classed('active', show);
55646                 shown = show;
55647
55648                 if (show) {
55649                     selection$$1.on('mousedown.background-inside', function() {
55650                         event.stopPropagation();
55651                     });
55652                     content
55653                         .style('display', 'block')
55654                         .style('right', '-300px')
55655                         .transition()
55656                         .duration(200)
55657                         .style('right', '0px');
55658                 } else {
55659                     content
55660                         .style('display', 'block')
55661                         .style('right', '0px')
55662                         .transition()
55663                         .duration(200)
55664                         .style('right', '-300px')
55665                         .on('end', function() {
55666                             select(this).style('display', 'none');
55667                         });
55668                     selection$$1.on('mousedown.background-inside', null);
55669                 }
55670             }
55671         }
55672
55673
55674         var content = selection$$1
55675                 .append('div')
55676                 .attr('class', 'fillL map-overlay col3 content hide'),
55677             tooltipBehavior = tooltip()
55678                 .placement((textDirection === 'rtl') ? 'right' : 'left')
55679                 .html(true)
55680                 .title(uiTooltipHtml(t('background.description'), key)),
55681             button = selection$$1
55682                 .append('button')
55683                 .attr('tabindex', -1)
55684                 .on('click', toggle)
55685                 .call(svgIcon('#icon-layers', 'light'))
55686                 .call(tooltipBehavior),
55687             shown = false;
55688
55689
55690         /* opacity switcher */
55691
55692         var opawrap = content
55693                 .append('div')
55694                 .attr('class', 'opacity-options-wrapper');
55695
55696         opawrap
55697             .append('h4')
55698             .text(t('background.title'));
55699
55700         var opacityList = opawrap
55701             .append('ul')
55702             .attr('class', 'opacity-options');
55703
55704         opacityList.selectAll('div.opacity')
55705             .data(opacities)
55706             .enter()
55707             .append('li')
55708             .attr('data-original-title', function(d) {
55709                 return t('background.percent_brightness', { opacity: (d * 100) });
55710             })
55711             .on('click.set-opacity', setOpacity)
55712             .html('<div class="select-box"></div>')
55713             .call(tooltip()
55714                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55715             .append('div')
55716             .attr('class', 'opacity')
55717             .style('opacity', function(d) { return 1.25 - d; });
55718
55719
55720         /* background switcher */
55721
55722         var backgroundList = content
55723             .append('ul')
55724             .attr('class', 'layer-list')
55725             .attr('dir', 'auto');
55726
55727         var custom = backgroundList
55728             .append('li')
55729             .attr('class', 'custom_layer')
55730             .datum(rendererBackgroundSource.Custom());
55731
55732         custom
55733             .append('button')
55734             .attr('class', 'layer-browse')
55735             .call(tooltip()
55736                 .title(t('background.custom_button'))
55737                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
55738             .on('click', editCustom)
55739             .call(svgIcon('#icon-search'));
55740
55741         var label = custom
55742             .append('label');
55743
55744         label
55745             .append('input')
55746             .attr('type', 'radio')
55747             .attr('name', 'layers')
55748             .on('change', function () {
55749                 if (customTemplate) {
55750                     setCustom(customTemplate);
55751                 } else {
55752                     editCustom();
55753                 }
55754             });
55755
55756         label
55757             .append('span')
55758             .text(t('background.custom'));
55759
55760         content
55761             .append('div')
55762             .attr('class', 'imagery-faq')
55763             .append('a')
55764             .attr('target', '_blank')
55765             .attr('tabindex', -1)
55766             .call(svgIcon('#icon-out-link', 'inline'))
55767             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
55768             .append('span')
55769             .text(t('background.imagery_source_faq'));
55770
55771         var overlayList = content
55772             .append('ul')
55773             .attr('class', 'layer-list');
55774
55775         var controls = content
55776             .append('div')
55777             .attr('class', 'controls-list');
55778
55779
55780         /* minimap toggle */
55781
55782         var minimapLabel = controls
55783             .append('label')
55784             .call(tooltip()
55785                 .html(true)
55786                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
55787                 .placement('top')
55788             );
55789
55790         minimapLabel
55791             .classed('minimap-toggle', true)
55792             .append('input')
55793             .attr('type', 'checkbox')
55794             .on('change', function() {
55795                 uiMapInMap.toggle();
55796                 event.preventDefault();
55797             });
55798
55799         minimapLabel
55800             .append('span')
55801             .text(t('background.minimap.description'));
55802
55803
55804         /* imagery offset controls */
55805
55806         var adjustments = content
55807             .append('div')
55808             .attr('class', 'adjustments');
55809
55810         adjustments
55811             .append('a')
55812             .text(t('background.fix_misalignment'))
55813             .attr('href', '#')
55814             .classed('hide-toggle', true)
55815             .classed('expanded', false)
55816             .on('click', function() {
55817                 if (event.button !== 0) return;
55818                 var exp = select(this).classed('expanded');
55819                 nudgeContainer.style('display', exp ? 'none' : 'block');
55820                 select(this).classed('expanded', !exp);
55821                 event.preventDefault();
55822             });
55823
55824         var nudgeContainer = adjustments
55825             .append('div')
55826             .attr('class', 'nudge-container cf')
55827             .style('display', 'none');
55828
55829         nudgeContainer
55830             .append('div')
55831             .attr('class', 'nudge-instructions')
55832             .text(t('background.offset'));
55833
55834         var nudgeRect = nudgeContainer
55835             .append('div')
55836             .attr('class', 'nudge-outer-rect')
55837             .on('mousedown', dragOffset);
55838
55839         nudgeRect
55840             .append('div')
55841             .attr('class', 'nudge-inner-rect')
55842             .append('input')
55843             .on('change', inputOffset)
55844             .on('mousedown', function() {
55845                 if (event.button !== 0) return;
55846                 event.stopPropagation();
55847             });
55848
55849         nudgeContainer
55850             .append('div')
55851             .selectAll('button')
55852             .data(directions).enter()
55853             .append('button')
55854             .attr('class', function(d) { return d[0] + ' nudge'; })
55855             .on('mousedown', function(d) {
55856                 if (event.button !== 0) return;
55857                 buttonOffset(d[1]);
55858             });
55859
55860         nudgeContainer
55861             .append('button')
55862             .attr('title', t('background.reset'))
55863             .attr('class', 'nudge-reset disabled')
55864             .on('click', resetOffset)
55865             .call(
55866                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
55867             );
55868
55869         context.map()
55870             .on('move.background-update', lodash.debounce(update, 1000));
55871
55872         context.background()
55873             .on('change.background-update', update);
55874
55875
55876         update();
55877         setOpacity(opacityDefault);
55878
55879         var keybinding = d3keybinding('background')
55880             .on(key, toggle)
55881             .on(uiCmd('⌘B'), quickSwitch)
55882             .on('F', hide)
55883             .on('H', hide);
55884
55885         select(document)
55886             .call(keybinding);
55887
55888         context.surface().on('mousedown.background-outside', hide);
55889         context.container().on('mousedown.background-outside', hide);
55890     }
55891
55892     return background;
55893 }
55894
55895 function uiContributors(context) {
55896     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
55897         limit = 4,
55898         hidden = false,
55899         wrap = select(null);
55900
55901
55902     function update() {
55903         var users = {},
55904             entities = context.intersects(context.map().extent());
55905
55906         entities.forEach(function(entity) {
55907             if (entity && entity.user) users[entity.user] = true;
55908         });
55909
55910         var u = Object.keys(users),
55911             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
55912
55913         wrap.html('')
55914             .call(svgIcon('#icon-nearby', 'pre-text light'));
55915
55916         var userList = select(document.createElement('span'));
55917
55918         userList.selectAll()
55919             .data(subset)
55920             .enter()
55921             .append('a')
55922             .attr('class', 'user-link')
55923             .attr('href', function(d) { return context.connection().userURL(d); })
55924             .attr('target', '_blank')
55925             .attr('tabindex', -1)
55926             .text(String);
55927
55928         if (u.length > limit) {
55929             var count = select(document.createElement('span'));
55930
55931             count.append('a')
55932                 .attr('target', '_blank')
55933                 .attr('tabindex', -1)
55934                 .attr('href', function() {
55935                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
55936                 })
55937                 .text(u.length - limit + 1);
55938
55939             wrap.append('span')
55940                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
55941
55942         } else {
55943             wrap.append('span')
55944                 .html(t('contributors.list', { users: userList.html() }));
55945         }
55946
55947         if (!u.length) {
55948             hidden = true;
55949             wrap
55950                 .transition()
55951                 .style('opacity', 0);
55952
55953         } else if (hidden) {
55954             wrap
55955                 .transition()
55956                 .style('opacity', 1);
55957         }
55958     }
55959
55960
55961     return function(selection$$1) {
55962         wrap = selection$$1;
55963         update();
55964
55965         context.connection().on('loaded.contributors', debouncedUpdate);
55966         context.map().on('move.contributors', debouncedUpdate);
55967     };
55968 }
55969
55970 function uiFeatureInfo(context) {
55971     function update(selection$$1) {
55972         var features = context.features(),
55973             stats = features.stats(),
55974             count = 0,
55975             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
55976                 if (stats[k]) {
55977                     count += stats[k];
55978                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
55979                 }
55980             }));
55981
55982         selection$$1.html('');
55983
55984         if (hiddenList.length) {
55985             var tooltipBehavior = tooltip()
55986                     .placement('top')
55987                     .html(true)
55988                     .title(function() {
55989                         return uiTooltipHtml(hiddenList.join('<br/>'));
55990                     });
55991
55992             var warning = selection$$1.append('a')
55993                 .attr('href', '#')
55994                 .attr('tabindex', -1)
55995                 .html(t('feature_info.hidden_warning', { count: count }))
55996                 .call(tooltipBehavior)
55997                 .on('click', function() {
55998                     tooltipBehavior.hide(warning);
55999                     // open map data panel?
56000                     event.preventDefault();
56001                 });
56002         }
56003
56004         selection$$1
56005             .classed('hide', !hiddenList.length);
56006     }
56007
56008
56009     return function(selection$$1) {
56010         update(selection$$1);
56011
56012         context.features().on('change.feature_info', function() {
56013             update(selection$$1);
56014         });
56015     };
56016 }
56017
56018 function uiFullScreen(context) {
56019     var element = context.container().node(),
56020         keybinding = d3keybinding('full-screen');
56021         // button;
56022
56023
56024     function getFullScreenFn() {
56025         if (element.requestFullscreen) {
56026             return element.requestFullscreen;
56027         } else if (element.msRequestFullscreen) {
56028             return element.msRequestFullscreen;
56029         } else if (element.mozRequestFullScreen) {
56030             return element.mozRequestFullScreen;
56031         } else if (element.webkitRequestFullscreen) {
56032             return element.webkitRequestFullscreen;
56033         }
56034     }
56035
56036
56037     function getExitFullScreenFn() {
56038         if (document.exitFullscreen) {
56039             return document.exitFullscreen;
56040         } else if (document.msExitFullscreen) {
56041             return document.msExitFullscreen;
56042         } else if (document.mozCancelFullScreen) {
56043             return document.mozCancelFullScreen;
56044         } else if (document.webkitExitFullscreen) {
56045             return document.webkitExitFullscreen;
56046         }
56047     }
56048
56049
56050     function isFullScreen() {
56051         return document.fullscreenElement ||
56052             document.mozFullScreenElement ||
56053             document.webkitFullscreenElement ||
56054             document.msFullscreenElement;
56055     }
56056
56057
56058     function isSupported() {
56059         return !!getFullScreenFn();
56060     }
56061
56062
56063     function fullScreen() {
56064         event.preventDefault();
56065         if (!isFullScreen()) {
56066             // button.classed('active', true);
56067             getFullScreenFn().apply(element);
56068         } else {
56069             // button.classed('active', false);
56070             getExitFullScreenFn().apply(document);
56071         }
56072     }
56073
56074
56075     return function() { // selection) {
56076         if (!isSupported())
56077             return;
56078
56079         // button = selection.append('button')
56080         //     .attr('title', t('full_screen'))
56081         //     .attr('tabindex', -1)
56082         //     .on('click', fullScreen)
56083         //     .call(tooltip);
56084
56085         // button.append('span')
56086         //     .attr('class', 'icon full-screen');
56087
56088         keybinding
56089             .on('f11', fullScreen)
56090             .on(uiCmd('⌘⇧F'), fullScreen);
56091
56092         select(document)
56093             .call(keybinding);
56094     };
56095 }
56096
56097 function uiModal(selection$$1, blocking) {
56098     var keybinding = d3keybinding('modal');
56099     var previous = selection$$1.select('div.modal');
56100     var animate = previous.empty();
56101
56102     previous.transition()
56103         .duration(200)
56104         .style('opacity', 0)
56105         .remove();
56106
56107     var shaded = selection$$1
56108         .append('div')
56109         .attr('class', 'shaded')
56110         .style('opacity', 0);
56111
56112     shaded.close = function() {
56113         shaded
56114             .transition()
56115             .duration(200)
56116             .style('opacity',0)
56117             .remove();
56118
56119         modal
56120             .transition()
56121             .duration(200)
56122             .style('top','0px');
56123
56124         keybinding.off();
56125     };
56126
56127
56128     var modal = shaded
56129         .append('div')
56130         .attr('class', 'modal fillL col6');
56131
56132     if (!blocking) {
56133         shaded.on('click.remove-modal', function() {
56134             if (event.target === this) {
56135                 shaded.close();
56136             }
56137         });
56138
56139         modal.append('button')
56140             .attr('class', 'close')
56141             .on('click', shaded.close)
56142             .call(svgIcon('#icon-close'));
56143
56144         keybinding
56145             .on('⌫', shaded.close)
56146             .on('⎋', shaded.close);
56147
56148         select(document)
56149             .call(keybinding);
56150     }
56151
56152     modal
56153         .append('div')
56154         .attr('class', 'content');
56155
56156     if (animate) {
56157         shaded.transition().style('opacity', 1);
56158     } else {
56159         shaded.style('opacity', 1);
56160     }
56161
56162
56163     return shaded;
56164 }
56165
56166 function uiLoading(context) {
56167     var message = '',
56168         blocking = false,
56169         modalSelection;
56170
56171
56172     var loading = function(selection) {
56173         modalSelection = uiModal(selection, blocking);
56174
56175         var loadertext = modalSelection.select('.content')
56176             .classed('loading-modal', true)
56177             .append('div')
56178             .attr('class', 'modal-section fillL');
56179
56180         loadertext
56181             .append('img')
56182             .attr('class', 'loader')
56183             .attr('src', context.imagePath('loader-white.gif'));
56184
56185         loadertext
56186             .append('h3')
56187             .text(message);
56188
56189         modalSelection.select('button.close')
56190             .attr('class', 'hide');
56191
56192         return loading;
56193     };
56194
56195
56196     loading.message = function(_) {
56197         if (!arguments.length) return message;
56198         message = _;
56199         return loading;
56200     };
56201
56202
56203     loading.blocking = function(_) {
56204         if (!arguments.length) return blocking;
56205         blocking = _;
56206         return loading;
56207     };
56208
56209
56210     loading.close = function() {
56211         modalSelection.remove();
56212     };
56213
56214
56215     return loading;
56216 }
56217
56218 function uiGeolocate(context) {
56219     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
56220         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
56221         timeoutId;
56222
56223
56224     function click() {
56225         context.enter(modeBrowse(context));
56226         context.container().call(locating);
56227         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
56228
56229         // This timeout ensures that we still call finish() even if
56230         // the user declines to share their location in Firefox
56231         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
56232     }
56233
56234
56235     function success(position) {
56236         var map = context.map(),
56237             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
56238                 .padByMeters(position.coords.accuracy);
56239
56240         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
56241         finish();
56242     }
56243
56244
56245     function error() {
56246         finish();
56247     }
56248
56249
56250     function finish() {
56251         locating.close();  // unblock ui
56252         if (timeoutId) { clearTimeout(timeoutId); }
56253         timeoutId = undefined;
56254     }
56255
56256
56257     return function(selection) {
56258         if (!navigator.geolocation) return;
56259
56260         selection
56261             .append('button')
56262             .attr('tabindex', -1)
56263             .attr('title', t('geolocate.title'))
56264             .on('click', click)
56265             .call(svgIcon('#icon-geolocate', 'light'))
56266             .call(tooltip()
56267                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
56268     };
56269 }
56270
56271 var marked = createCommonjsModule(function (module, exports) {
56272 /**
56273  * marked - a markdown parser
56274  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
56275  * https://github.com/chjj/marked
56276  */
56277
56278 (function() {
56279
56280 /**
56281  * Block-Level Grammar
56282  */
56283
56284 var block = {
56285   newline: /^\n+/,
56286   code: /^( {4}[^\n]+\n*)+/,
56287   fences: noop,
56288   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
56289   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
56290   nptable: noop,
56291   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
56292   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
56293   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
56294   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
56295   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
56296   table: noop,
56297   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
56298   text: /^[^\n]+/
56299 };
56300
56301 block.bullet = /(?:[*+-]|\d+\.)/;
56302 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
56303 block.item = replace(block.item, 'gm')
56304   (/bull/g, block.bullet)
56305   ();
56306
56307 block.list = replace(block.list)
56308   (/bull/g, block.bullet)
56309   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
56310   ('def', '\\n+(?=' + block.def.source + ')')
56311   ();
56312
56313 block.blockquote = replace(block.blockquote)
56314   ('def', block.def)
56315   ();
56316
56317 block._tag = '(?!(?:'
56318   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
56319   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
56320   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
56321
56322 block.html = replace(block.html)
56323   ('comment', /<!--[\s\S]*?-->/)
56324   ('closed', /<(tag)[\s\S]+?<\/\1>/)
56325   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
56326   (/tag/g, block._tag)
56327   ();
56328
56329 block.paragraph = replace(block.paragraph)
56330   ('hr', block.hr)
56331   ('heading', block.heading)
56332   ('lheading', block.lheading)
56333   ('blockquote', block.blockquote)
56334   ('tag', '<' + block._tag)
56335   ('def', block.def)
56336   ();
56337
56338 /**
56339  * Normal Block Grammar
56340  */
56341
56342 block.normal = merge({}, block);
56343
56344 /**
56345  * GFM Block Grammar
56346  */
56347
56348 block.gfm = merge({}, block.normal, {
56349   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
56350   paragraph: /^/,
56351   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
56352 });
56353
56354 block.gfm.paragraph = replace(block.paragraph)
56355   ('(?!', '(?!'
56356     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
56357     + block.list.source.replace('\\1', '\\3') + '|')
56358   ();
56359
56360 /**
56361  * GFM + Tables Block Grammar
56362  */
56363
56364 block.tables = merge({}, block.gfm, {
56365   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
56366   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
56367 });
56368
56369 /**
56370  * Block Lexer
56371  */
56372
56373 function Lexer(options) {
56374   this.tokens = [];
56375   this.tokens.links = {};
56376   this.options = options || marked.defaults;
56377   this.rules = block.normal;
56378
56379   if (this.options.gfm) {
56380     if (this.options.tables) {
56381       this.rules = block.tables;
56382     } else {
56383       this.rules = block.gfm;
56384     }
56385   }
56386 }
56387
56388 /**
56389  * Expose Block Rules
56390  */
56391
56392 Lexer.rules = block;
56393
56394 /**
56395  * Static Lex Method
56396  */
56397
56398 Lexer.lex = function(src, options) {
56399   var lexer = new Lexer(options);
56400   return lexer.lex(src);
56401 };
56402
56403 /**
56404  * Preprocessing
56405  */
56406
56407 Lexer.prototype.lex = function(src) {
56408   src = src
56409     .replace(/\r\n|\r/g, '\n')
56410     .replace(/\t/g, '    ')
56411     .replace(/\u00a0/g, ' ')
56412     .replace(/\u2424/g, '\n');
56413
56414   return this.token(src, true);
56415 };
56416
56417 /**
56418  * Lexing
56419  */
56420
56421 Lexer.prototype.token = function(src, top, bq) {
56422   var src = src.replace(/^ +$/gm, '')
56423     , next
56424     , loose
56425     , cap
56426     , bull
56427     , b
56428     , item
56429     , space
56430     , i
56431     , l;
56432
56433   while (src) {
56434     // newline
56435     if (cap = this.rules.newline.exec(src)) {
56436       src = src.substring(cap[0].length);
56437       if (cap[0].length > 1) {
56438         this.tokens.push({
56439           type: 'space'
56440         });
56441       }
56442     }
56443
56444     // code
56445     if (cap = this.rules.code.exec(src)) {
56446       src = src.substring(cap[0].length);
56447       cap = cap[0].replace(/^ {4}/gm, '');
56448       this.tokens.push({
56449         type: 'code',
56450         text: !this.options.pedantic
56451           ? cap.replace(/\n+$/, '')
56452           : cap
56453       });
56454       continue;
56455     }
56456
56457     // fences (gfm)
56458     if (cap = this.rules.fences.exec(src)) {
56459       src = src.substring(cap[0].length);
56460       this.tokens.push({
56461         type: 'code',
56462         lang: cap[2],
56463         text: cap[3] || ''
56464       });
56465       continue;
56466     }
56467
56468     // heading
56469     if (cap = this.rules.heading.exec(src)) {
56470       src = src.substring(cap[0].length);
56471       this.tokens.push({
56472         type: 'heading',
56473         depth: cap[1].length,
56474         text: cap[2]
56475       });
56476       continue;
56477     }
56478
56479     // table no leading pipe (gfm)
56480     if (top && (cap = this.rules.nptable.exec(src))) {
56481       src = src.substring(cap[0].length);
56482
56483       item = {
56484         type: 'table',
56485         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56486         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56487         cells: cap[3].replace(/\n$/, '').split('\n')
56488       };
56489
56490       for (i = 0; i < item.align.length; i++) {
56491         if (/^ *-+: *$/.test(item.align[i])) {
56492           item.align[i] = 'right';
56493         } else if (/^ *:-+: *$/.test(item.align[i])) {
56494           item.align[i] = 'center';
56495         } else if (/^ *:-+ *$/.test(item.align[i])) {
56496           item.align[i] = 'left';
56497         } else {
56498           item.align[i] = null;
56499         }
56500       }
56501
56502       for (i = 0; i < item.cells.length; i++) {
56503         item.cells[i] = item.cells[i].split(/ *\| */);
56504       }
56505
56506       this.tokens.push(item);
56507
56508       continue;
56509     }
56510
56511     // lheading
56512     if (cap = this.rules.lheading.exec(src)) {
56513       src = src.substring(cap[0].length);
56514       this.tokens.push({
56515         type: 'heading',
56516         depth: cap[2] === '=' ? 1 : 2,
56517         text: cap[1]
56518       });
56519       continue;
56520     }
56521
56522     // hr
56523     if (cap = this.rules.hr.exec(src)) {
56524       src = src.substring(cap[0].length);
56525       this.tokens.push({
56526         type: 'hr'
56527       });
56528       continue;
56529     }
56530
56531     // blockquote
56532     if (cap = this.rules.blockquote.exec(src)) {
56533       src = src.substring(cap[0].length);
56534
56535       this.tokens.push({
56536         type: 'blockquote_start'
56537       });
56538
56539       cap = cap[0].replace(/^ *> ?/gm, '');
56540
56541       // Pass `top` to keep the current
56542       // "toplevel" state. This is exactly
56543       // how markdown.pl works.
56544       this.token(cap, top, true);
56545
56546       this.tokens.push({
56547         type: 'blockquote_end'
56548       });
56549
56550       continue;
56551     }
56552
56553     // list
56554     if (cap = this.rules.list.exec(src)) {
56555       src = src.substring(cap[0].length);
56556       bull = cap[2];
56557
56558       this.tokens.push({
56559         type: 'list_start',
56560         ordered: bull.length > 1
56561       });
56562
56563       // Get each top-level item.
56564       cap = cap[0].match(this.rules.item);
56565
56566       next = false;
56567       l = cap.length;
56568       i = 0;
56569
56570       for (; i < l; i++) {
56571         item = cap[i];
56572
56573         // Remove the list item's bullet
56574         // so it is seen as the next token.
56575         space = item.length;
56576         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
56577
56578         // Outdent whatever the
56579         // list item contains. Hacky.
56580         if (~item.indexOf('\n ')) {
56581           space -= item.length;
56582           item = !this.options.pedantic
56583             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
56584             : item.replace(/^ {1,4}/gm, '');
56585         }
56586
56587         // Determine whether the next list item belongs here.
56588         // Backpedal if it does not belong in this list.
56589         if (this.options.smartLists && i !== l - 1) {
56590           b = block.bullet.exec(cap[i + 1])[0];
56591           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
56592             src = cap.slice(i + 1).join('\n') + src;
56593             i = l - 1;
56594           }
56595         }
56596
56597         // Determine whether item is loose or not.
56598         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
56599         // for discount behavior.
56600         loose = next || /\n\n(?!\s*$)/.test(item);
56601         if (i !== l - 1) {
56602           next = item.charAt(item.length - 1) === '\n';
56603           if (!loose) loose = next;
56604         }
56605
56606         this.tokens.push({
56607           type: loose
56608             ? 'loose_item_start'
56609             : 'list_item_start'
56610         });
56611
56612         // Recurse.
56613         this.token(item, false, bq);
56614
56615         this.tokens.push({
56616           type: 'list_item_end'
56617         });
56618       }
56619
56620       this.tokens.push({
56621         type: 'list_end'
56622       });
56623
56624       continue;
56625     }
56626
56627     // html
56628     if (cap = this.rules.html.exec(src)) {
56629       src = src.substring(cap[0].length);
56630       this.tokens.push({
56631         type: this.options.sanitize
56632           ? 'paragraph'
56633           : 'html',
56634         pre: !this.options.sanitizer
56635           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
56636         text: cap[0]
56637       });
56638       continue;
56639     }
56640
56641     // def
56642     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
56643       src = src.substring(cap[0].length);
56644       this.tokens.links[cap[1].toLowerCase()] = {
56645         href: cap[2],
56646         title: cap[3]
56647       };
56648       continue;
56649     }
56650
56651     // table (gfm)
56652     if (top && (cap = this.rules.table.exec(src))) {
56653       src = src.substring(cap[0].length);
56654
56655       item = {
56656         type: 'table',
56657         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
56658         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
56659         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
56660       };
56661
56662       for (i = 0; i < item.align.length; i++) {
56663         if (/^ *-+: *$/.test(item.align[i])) {
56664           item.align[i] = 'right';
56665         } else if (/^ *:-+: *$/.test(item.align[i])) {
56666           item.align[i] = 'center';
56667         } else if (/^ *:-+ *$/.test(item.align[i])) {
56668           item.align[i] = 'left';
56669         } else {
56670           item.align[i] = null;
56671         }
56672       }
56673
56674       for (i = 0; i < item.cells.length; i++) {
56675         item.cells[i] = item.cells[i]
56676           .replace(/^ *\| *| *\| *$/g, '')
56677           .split(/ *\| */);
56678       }
56679
56680       this.tokens.push(item);
56681
56682       continue;
56683     }
56684
56685     // top-level paragraph
56686     if (top && (cap = this.rules.paragraph.exec(src))) {
56687       src = src.substring(cap[0].length);
56688       this.tokens.push({
56689         type: 'paragraph',
56690         text: cap[1].charAt(cap[1].length - 1) === '\n'
56691           ? cap[1].slice(0, -1)
56692           : cap[1]
56693       });
56694       continue;
56695     }
56696
56697     // text
56698     if (cap = this.rules.text.exec(src)) {
56699       // Top-level should never reach here.
56700       src = src.substring(cap[0].length);
56701       this.tokens.push({
56702         type: 'text',
56703         text: cap[0]
56704       });
56705       continue;
56706     }
56707
56708     if (src) {
56709       throw new
56710         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56711     }
56712   }
56713
56714   return this.tokens;
56715 };
56716
56717 /**
56718  * Inline-Level Grammar
56719  */
56720
56721 var inline = {
56722   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
56723   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
56724   url: noop,
56725   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
56726   link: /^!?\[(inside)\]\(href\)/,
56727   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
56728   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
56729   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
56730   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
56731   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
56732   br: /^ {2,}\n(?!\s*$)/,
56733   del: noop,
56734   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
56735 };
56736
56737 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
56738 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
56739
56740 inline.link = replace(inline.link)
56741   ('inside', inline._inside)
56742   ('href', inline._href)
56743   ();
56744
56745 inline.reflink = replace(inline.reflink)
56746   ('inside', inline._inside)
56747   ();
56748
56749 /**
56750  * Normal Inline Grammar
56751  */
56752
56753 inline.normal = merge({}, inline);
56754
56755 /**
56756  * Pedantic Inline Grammar
56757  */
56758
56759 inline.pedantic = merge({}, inline.normal, {
56760   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
56761   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
56762 });
56763
56764 /**
56765  * GFM Inline Grammar
56766  */
56767
56768 inline.gfm = merge({}, inline.normal, {
56769   escape: replace(inline.escape)('])', '~|])')(),
56770   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
56771   del: /^~~(?=\S)([\s\S]*?\S)~~/,
56772   text: replace(inline.text)
56773     (']|', '~]|')
56774     ('|', '|https?://|')
56775     ()
56776 });
56777
56778 /**
56779  * GFM + Line Breaks Inline Grammar
56780  */
56781
56782 inline.breaks = merge({}, inline.gfm, {
56783   br: replace(inline.br)('{2,}', '*')(),
56784   text: replace(inline.gfm.text)('{2,}', '*')()
56785 });
56786
56787 /**
56788  * Inline Lexer & Compiler
56789  */
56790
56791 function InlineLexer(links, options) {
56792   this.options = options || marked.defaults;
56793   this.links = links;
56794   this.rules = inline.normal;
56795   this.renderer = this.options.renderer || new Renderer;
56796   this.renderer.options = this.options;
56797
56798   if (!this.links) {
56799     throw new
56800       Error('Tokens array requires a `links` property.');
56801   }
56802
56803   if (this.options.gfm) {
56804     if (this.options.breaks) {
56805       this.rules = inline.breaks;
56806     } else {
56807       this.rules = inline.gfm;
56808     }
56809   } else if (this.options.pedantic) {
56810     this.rules = inline.pedantic;
56811   }
56812 }
56813
56814 /**
56815  * Expose Inline Rules
56816  */
56817
56818 InlineLexer.rules = inline;
56819
56820 /**
56821  * Static Lexing/Compiling Method
56822  */
56823
56824 InlineLexer.output = function(src, links, options) {
56825   var inline = new InlineLexer(links, options);
56826   return inline.output(src);
56827 };
56828
56829 /**
56830  * Lexing/Compiling
56831  */
56832
56833 InlineLexer.prototype.output = function(src) {
56834   var out = ''
56835     , link
56836     , text
56837     , href
56838     , cap;
56839
56840   while (src) {
56841     // escape
56842     if (cap = this.rules.escape.exec(src)) {
56843       src = src.substring(cap[0].length);
56844       out += cap[1];
56845       continue;
56846     }
56847
56848     // autolink
56849     if (cap = this.rules.autolink.exec(src)) {
56850       src = src.substring(cap[0].length);
56851       if (cap[2] === '@') {
56852         text = cap[1].charAt(6) === ':'
56853           ? this.mangle(cap[1].substring(7))
56854           : this.mangle(cap[1]);
56855         href = this.mangle('mailto:') + text;
56856       } else {
56857         text = escape(cap[1]);
56858         href = text;
56859       }
56860       out += this.renderer.link(href, null, text);
56861       continue;
56862     }
56863
56864     // url (gfm)
56865     if (!this.inLink && (cap = this.rules.url.exec(src))) {
56866       src = src.substring(cap[0].length);
56867       text = escape(cap[1]);
56868       href = text;
56869       out += this.renderer.link(href, null, text);
56870       continue;
56871     }
56872
56873     // tag
56874     if (cap = this.rules.tag.exec(src)) {
56875       if (!this.inLink && /^<a /i.test(cap[0])) {
56876         this.inLink = true;
56877       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
56878         this.inLink = false;
56879       }
56880       src = src.substring(cap[0].length);
56881       out += this.options.sanitize
56882         ? this.options.sanitizer
56883           ? this.options.sanitizer(cap[0])
56884           : escape(cap[0])
56885         : cap[0];
56886       continue;
56887     }
56888
56889     // link
56890     if (cap = this.rules.link.exec(src)) {
56891       src = src.substring(cap[0].length);
56892       this.inLink = true;
56893       out += this.outputLink(cap, {
56894         href: cap[2],
56895         title: cap[3]
56896       });
56897       this.inLink = false;
56898       continue;
56899     }
56900
56901     // reflink, nolink
56902     if ((cap = this.rules.reflink.exec(src))
56903         || (cap = this.rules.nolink.exec(src))) {
56904       src = src.substring(cap[0].length);
56905       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
56906       link = this.links[link.toLowerCase()];
56907       if (!link || !link.href) {
56908         out += cap[0].charAt(0);
56909         src = cap[0].substring(1) + src;
56910         continue;
56911       }
56912       this.inLink = true;
56913       out += this.outputLink(cap, link);
56914       this.inLink = false;
56915       continue;
56916     }
56917
56918     // strong
56919     if (cap = this.rules.strong.exec(src)) {
56920       src = src.substring(cap[0].length);
56921       out += this.renderer.strong(this.output(cap[2] || cap[1]));
56922       continue;
56923     }
56924
56925     // em
56926     if (cap = this.rules.em.exec(src)) {
56927       src = src.substring(cap[0].length);
56928       out += this.renderer.em(this.output(cap[2] || cap[1]));
56929       continue;
56930     }
56931
56932     // code
56933     if (cap = this.rules.code.exec(src)) {
56934       src = src.substring(cap[0].length);
56935       out += this.renderer.codespan(escape(cap[2], true));
56936       continue;
56937     }
56938
56939     // br
56940     if (cap = this.rules.br.exec(src)) {
56941       src = src.substring(cap[0].length);
56942       out += this.renderer.br();
56943       continue;
56944     }
56945
56946     // del (gfm)
56947     if (cap = this.rules.del.exec(src)) {
56948       src = src.substring(cap[0].length);
56949       out += this.renderer.del(this.output(cap[1]));
56950       continue;
56951     }
56952
56953     // text
56954     if (cap = this.rules.text.exec(src)) {
56955       src = src.substring(cap[0].length);
56956       out += this.renderer.text(escape(this.smartypants(cap[0])));
56957       continue;
56958     }
56959
56960     if (src) {
56961       throw new
56962         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56963     }
56964   }
56965
56966   return out;
56967 };
56968
56969 /**
56970  * Compile Link
56971  */
56972
56973 InlineLexer.prototype.outputLink = function(cap, link) {
56974   var href = escape(link.href)
56975     , title = link.title ? escape(link.title) : null;
56976
56977   return cap[0].charAt(0) !== '!'
56978     ? this.renderer.link(href, title, this.output(cap[1]))
56979     : this.renderer.image(href, title, escape(cap[1]));
56980 };
56981
56982 /**
56983  * Smartypants Transformations
56984  */
56985
56986 InlineLexer.prototype.smartypants = function(text) {
56987   if (!this.options.smartypants) return text;
56988   return text
56989     // em-dashes
56990     .replace(/---/g, '\u2014')
56991     // en-dashes
56992     .replace(/--/g, '\u2013')
56993     // opening singles
56994     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
56995     // closing singles & apostrophes
56996     .replace(/'/g, '\u2019')
56997     // opening doubles
56998     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
56999     // closing doubles
57000     .replace(/"/g, '\u201d')
57001     // ellipses
57002     .replace(/\.{3}/g, '\u2026');
57003 };
57004
57005 /**
57006  * Mangle Links
57007  */
57008
57009 InlineLexer.prototype.mangle = function(text) {
57010   if (!this.options.mangle) return text;
57011   var out = ''
57012     , l = text.length
57013     , i = 0
57014     , ch;
57015
57016   for (; i < l; i++) {
57017     ch = text.charCodeAt(i);
57018     if (Math.random() > 0.5) {
57019       ch = 'x' + ch.toString(16);
57020     }
57021     out += '&#' + ch + ';';
57022   }
57023
57024   return out;
57025 };
57026
57027 /**
57028  * Renderer
57029  */
57030
57031 function Renderer(options) {
57032   this.options = options || {};
57033 }
57034
57035 Renderer.prototype.code = function(code, lang, escaped) {
57036   if (this.options.highlight) {
57037     var out = this.options.highlight(code, lang);
57038     if (out != null && out !== code) {
57039       escaped = true;
57040       code = out;
57041     }
57042   }
57043
57044   if (!lang) {
57045     return '<pre><code>'
57046       + (escaped ? code : escape(code, true))
57047       + '\n</code></pre>';
57048   }
57049
57050   return '<pre><code class="'
57051     + this.options.langPrefix
57052     + escape(lang, true)
57053     + '">'
57054     + (escaped ? code : escape(code, true))
57055     + '\n</code></pre>\n';
57056 };
57057
57058 Renderer.prototype.blockquote = function(quote) {
57059   return '<blockquote>\n' + quote + '</blockquote>\n';
57060 };
57061
57062 Renderer.prototype.html = function(html) {
57063   return html;
57064 };
57065
57066 Renderer.prototype.heading = function(text, level, raw) {
57067   return '<h'
57068     + level
57069     + ' id="'
57070     + this.options.headerPrefix
57071     + raw.toLowerCase().replace(/[^\w]+/g, '-')
57072     + '">'
57073     + text
57074     + '</h'
57075     + level
57076     + '>\n';
57077 };
57078
57079 Renderer.prototype.hr = function() {
57080   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
57081 };
57082
57083 Renderer.prototype.list = function(body, ordered) {
57084   var type = ordered ? 'ol' : 'ul';
57085   return '<' + type + '>\n' + body + '</' + type + '>\n';
57086 };
57087
57088 Renderer.prototype.listitem = function(text) {
57089   return '<li>' + text + '</li>\n';
57090 };
57091
57092 Renderer.prototype.paragraph = function(text) {
57093   return '<p>' + text + '</p>\n';
57094 };
57095
57096 Renderer.prototype.table = function(header, body) {
57097   return '<table>\n'
57098     + '<thead>\n'
57099     + header
57100     + '</thead>\n'
57101     + '<tbody>\n'
57102     + body
57103     + '</tbody>\n'
57104     + '</table>\n';
57105 };
57106
57107 Renderer.prototype.tablerow = function(content) {
57108   return '<tr>\n' + content + '</tr>\n';
57109 };
57110
57111 Renderer.prototype.tablecell = function(content, flags) {
57112   var type = flags.header ? 'th' : 'td';
57113   var tag = flags.align
57114     ? '<' + type + ' style="text-align:' + flags.align + '">'
57115     : '<' + type + '>';
57116   return tag + content + '</' + type + '>\n';
57117 };
57118
57119 // span level renderer
57120 Renderer.prototype.strong = function(text) {
57121   return '<strong>' + text + '</strong>';
57122 };
57123
57124 Renderer.prototype.em = function(text) {
57125   return '<em>' + text + '</em>';
57126 };
57127
57128 Renderer.prototype.codespan = function(text) {
57129   return '<code>' + text + '</code>';
57130 };
57131
57132 Renderer.prototype.br = function() {
57133   return this.options.xhtml ? '<br/>' : '<br>';
57134 };
57135
57136 Renderer.prototype.del = function(text) {
57137   return '<del>' + text + '</del>';
57138 };
57139
57140 Renderer.prototype.link = function(href, title, text) {
57141   if (this.options.sanitize) {
57142     try {
57143       var prot = decodeURIComponent(unescape(href))
57144         .replace(/[^\w:]/g, '')
57145         .toLowerCase();
57146     } catch (e) {
57147       return '';
57148     }
57149     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
57150       return '';
57151     }
57152   }
57153   var out = '<a href="' + href + '"';
57154   if (title) {
57155     out += ' title="' + title + '"';
57156   }
57157   out += '>' + text + '</a>';
57158   return out;
57159 };
57160
57161 Renderer.prototype.image = function(href, title, text) {
57162   var out = '<img src="' + href + '" alt="' + text + '"';
57163   if (title) {
57164     out += ' title="' + title + '"';
57165   }
57166   out += this.options.xhtml ? '/>' : '>';
57167   return out;
57168 };
57169
57170 Renderer.prototype.text = function(text) {
57171   return text;
57172 };
57173
57174 /**
57175  * Parsing & Compiling
57176  */
57177
57178 function Parser(options) {
57179   this.tokens = [];
57180   this.token = null;
57181   this.options = options || marked.defaults;
57182   this.options.renderer = this.options.renderer || new Renderer;
57183   this.renderer = this.options.renderer;
57184   this.renderer.options = this.options;
57185 }
57186
57187 /**
57188  * Static Parse Method
57189  */
57190
57191 Parser.parse = function(src, options, renderer) {
57192   var parser = new Parser(options, renderer);
57193   return parser.parse(src);
57194 };
57195
57196 /**
57197  * Parse Loop
57198  */
57199
57200 Parser.prototype.parse = function(src) {
57201   this.inline = new InlineLexer(src.links, this.options, this.renderer);
57202   this.tokens = src.reverse();
57203
57204   var out = '';
57205   while (this.next()) {
57206     out += this.tok();
57207   }
57208
57209   return out;
57210 };
57211
57212 /**
57213  * Next Token
57214  */
57215
57216 Parser.prototype.next = function() {
57217   return this.token = this.tokens.pop();
57218 };
57219
57220 /**
57221  * Preview Next Token
57222  */
57223
57224 Parser.prototype.peek = function() {
57225   return this.tokens[this.tokens.length - 1] || 0;
57226 };
57227
57228 /**
57229  * Parse Text Tokens
57230  */
57231
57232 Parser.prototype.parseText = function() {
57233   var body = this.token.text;
57234
57235   while (this.peek().type === 'text') {
57236     body += '\n' + this.next().text;
57237   }
57238
57239   return this.inline.output(body);
57240 };
57241
57242 /**
57243  * Parse Current Token
57244  */
57245
57246 Parser.prototype.tok = function() {
57247   switch (this.token.type) {
57248     case 'space': {
57249       return '';
57250     }
57251     case 'hr': {
57252       return this.renderer.hr();
57253     }
57254     case 'heading': {
57255       return this.renderer.heading(
57256         this.inline.output(this.token.text),
57257         this.token.depth,
57258         this.token.text);
57259     }
57260     case 'code': {
57261       return this.renderer.code(this.token.text,
57262         this.token.lang,
57263         this.token.escaped);
57264     }
57265     case 'table': {
57266       var header = ''
57267         , body = ''
57268         , i
57269         , row
57270         , cell
57271         , flags
57272         , j;
57273
57274       // header
57275       cell = '';
57276       for (i = 0; i < this.token.header.length; i++) {
57277         flags = { header: true, align: this.token.align[i] };
57278         cell += this.renderer.tablecell(
57279           this.inline.output(this.token.header[i]),
57280           { header: true, align: this.token.align[i] }
57281         );
57282       }
57283       header += this.renderer.tablerow(cell);
57284
57285       for (i = 0; i < this.token.cells.length; i++) {
57286         row = this.token.cells[i];
57287
57288         cell = '';
57289         for (j = 0; j < row.length; j++) {
57290           cell += this.renderer.tablecell(
57291             this.inline.output(row[j]),
57292             { header: false, align: this.token.align[j] }
57293           );
57294         }
57295
57296         body += this.renderer.tablerow(cell);
57297       }
57298       return this.renderer.table(header, body);
57299     }
57300     case 'blockquote_start': {
57301       var body = '';
57302
57303       while (this.next().type !== 'blockquote_end') {
57304         body += this.tok();
57305       }
57306
57307       return this.renderer.blockquote(body);
57308     }
57309     case 'list_start': {
57310       var body = ''
57311         , ordered = this.token.ordered;
57312
57313       while (this.next().type !== 'list_end') {
57314         body += this.tok();
57315       }
57316
57317       return this.renderer.list(body, ordered);
57318     }
57319     case 'list_item_start': {
57320       var body = '';
57321
57322       while (this.next().type !== 'list_item_end') {
57323         body += this.token.type === 'text'
57324           ? this.parseText()
57325           : this.tok();
57326       }
57327
57328       return this.renderer.listitem(body);
57329     }
57330     case 'loose_item_start': {
57331       var body = '';
57332
57333       while (this.next().type !== 'list_item_end') {
57334         body += this.tok();
57335       }
57336
57337       return this.renderer.listitem(body);
57338     }
57339     case 'html': {
57340       var html = !this.token.pre && !this.options.pedantic
57341         ? this.inline.output(this.token.text)
57342         : this.token.text;
57343       return this.renderer.html(html);
57344     }
57345     case 'paragraph': {
57346       return this.renderer.paragraph(this.inline.output(this.token.text));
57347     }
57348     case 'text': {
57349       return this.renderer.paragraph(this.parseText());
57350     }
57351   }
57352 };
57353
57354 /**
57355  * Helpers
57356  */
57357
57358 function escape(html, encode) {
57359   return html
57360     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
57361     .replace(/</g, '&lt;')
57362     .replace(/>/g, '&gt;')
57363     .replace(/"/g, '&quot;')
57364     .replace(/'/g, '&#39;');
57365 }
57366
57367 function unescape(html) {
57368         // explicitly match decimal, hex, and named HTML entities 
57369   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
57370     n = n.toLowerCase();
57371     if (n === 'colon') return ':';
57372     if (n.charAt(0) === '#') {
57373       return n.charAt(1) === 'x'
57374         ? String.fromCharCode(parseInt(n.substring(2), 16))
57375         : String.fromCharCode(+n.substring(1));
57376     }
57377     return '';
57378   });
57379 }
57380
57381 function replace(regex, opt) {
57382   regex = regex.source;
57383   opt = opt || '';
57384   return function self(name, val) {
57385     if (!name) return new RegExp(regex, opt);
57386     val = val.source || val;
57387     val = val.replace(/(^|[^\[])\^/g, '$1');
57388     regex = regex.replace(name, val);
57389     return self;
57390   };
57391 }
57392
57393 function noop() {}
57394 noop.exec = noop;
57395
57396 function merge(obj) {
57397   var i = 1
57398     , target
57399     , key;
57400
57401   for (; i < arguments.length; i++) {
57402     target = arguments[i];
57403     for (key in target) {
57404       if (Object.prototype.hasOwnProperty.call(target, key)) {
57405         obj[key] = target[key];
57406       }
57407     }
57408   }
57409
57410   return obj;
57411 }
57412
57413
57414 /**
57415  * Marked
57416  */
57417
57418 function marked(src, opt, callback) {
57419   if (callback || typeof opt === 'function') {
57420     if (!callback) {
57421       callback = opt;
57422       opt = null;
57423     }
57424
57425     opt = merge({}, marked.defaults, opt || {});
57426
57427     var highlight = opt.highlight
57428       , tokens
57429       , pending
57430       , i = 0;
57431
57432     try {
57433       tokens = Lexer.lex(src, opt);
57434     } catch (e) {
57435       return callback(e);
57436     }
57437
57438     pending = tokens.length;
57439
57440     var done = function(err) {
57441       if (err) {
57442         opt.highlight = highlight;
57443         return callback(err);
57444       }
57445
57446       var out;
57447
57448       try {
57449         out = Parser.parse(tokens, opt);
57450       } catch (e) {
57451         err = e;
57452       }
57453
57454       opt.highlight = highlight;
57455
57456       return err
57457         ? callback(err)
57458         : callback(null, out);
57459     };
57460
57461     if (!highlight || highlight.length < 3) {
57462       return done();
57463     }
57464
57465     delete opt.highlight;
57466
57467     if (!pending) return done();
57468
57469     for (; i < tokens.length; i++) {
57470       (function(token) {
57471         if (token.type !== 'code') {
57472           return --pending || done();
57473         }
57474         return highlight(token.text, token.lang, function(err, code) {
57475           if (err) return done(err);
57476           if (code == null || code === token.text) {
57477             return --pending || done();
57478           }
57479           token.text = code;
57480           token.escaped = true;
57481           --pending || done();
57482         });
57483       })(tokens[i]);
57484     }
57485
57486     return;
57487   }
57488   try {
57489     if (opt) opt = merge({}, marked.defaults, opt);
57490     return Parser.parse(Lexer.lex(src, opt), opt);
57491   } catch (e) {
57492     e.message += '\nPlease report this to https://github.com/chjj/marked.';
57493     if ((opt || marked.defaults).silent) {
57494       return '<p>An error occured:</p><pre>'
57495         + escape(e.message + '', true)
57496         + '</pre>';
57497     }
57498     throw e;
57499   }
57500 }
57501
57502 /**
57503  * Options
57504  */
57505
57506 marked.options =
57507 marked.setOptions = function(opt) {
57508   merge(marked.defaults, opt);
57509   return marked;
57510 };
57511
57512 marked.defaults = {
57513   gfm: true,
57514   tables: true,
57515   breaks: false,
57516   pedantic: false,
57517   sanitize: false,
57518   sanitizer: null,
57519   mangle: true,
57520   smartLists: false,
57521   silent: false,
57522   highlight: null,
57523   langPrefix: 'lang-',
57524   smartypants: false,
57525   headerPrefix: '',
57526   renderer: new Renderer,
57527   xhtml: false
57528 };
57529
57530 /**
57531  * Expose
57532  */
57533
57534 marked.Parser = Parser;
57535 marked.parser = Parser.parse;
57536
57537 marked.Renderer = Renderer;
57538
57539 marked.Lexer = Lexer;
57540 marked.lexer = Lexer.lex;
57541
57542 marked.InlineLexer = InlineLexer;
57543 marked.inlineLexer = InlineLexer.output;
57544
57545 marked.parse = marked;
57546
57547 {
57548   module.exports = marked;
57549 }
57550
57551 }).call(function() {
57552   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
57553 }());
57554 });
57555
57556 // toggles the visibility of ui elements, using a combination of the
57557 // hide class, which sets display=none, and a d3 transition for opacity.
57558 // this will cause blinking when called repeatedly, so check that the
57559 // value actually changes between calls.
57560 function uiToggle(show, callback) {
57561     return function(selection$$1) {
57562         selection$$1
57563             .style('opacity', show ? 0 : 1)
57564             .classed('hide', false)
57565             .transition()
57566             .style('opacity', show ? 1 : 0)
57567             .on('end', function() {
57568                 select(this)
57569                     .classed('hide', !show)
57570                     .style('opacity', null);
57571                 if (callback) callback.apply(this);
57572             });
57573     };
57574 }
57575
57576 // Tooltips and svg mask used to highlight certain features
57577 function d3curtain() {
57578
57579     var dispatch$$1 = dispatch(),
57580         surface = select(null),
57581         tooltip = select(null),
57582         darkness = select(null);
57583
57584     function curtain(selection$$1) {
57585         surface = selection$$1
57586             .append('svg')
57587             .attr('id', 'curtain')
57588             .style('z-index', 1000)
57589             .style('pointer-events', 'none')
57590             .style('position', 'absolute')
57591             .style('top', 0)
57592             .style('left', 0);
57593
57594         darkness = surface.append('path')
57595             .attr('x', 0)
57596             .attr('y', 0)
57597             .attr('class', 'curtain-darkness');
57598
57599         select(window).on('resize.curtain', resize);
57600
57601         tooltip = selection$$1.append('div')
57602             .attr('class', 'tooltip')
57603             .style('z-index', 1002);
57604
57605         tooltip
57606             .append('div')
57607             .attr('class', 'tooltip-arrow');
57608
57609         tooltip
57610             .append('div')
57611             .attr('class', 'tooltip-inner');
57612
57613         resize();
57614
57615
57616         function resize() {
57617             surface
57618                 .attr('width', window.innerWidth)
57619                 .attr('height', window.innerHeight);
57620             curtain.cut(darkness.datum());
57621         }
57622     }
57623
57624
57625     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
57626         if (typeof box === 'string') box = select(box).node();
57627         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
57628
57629         curtain.cut(box, duration);
57630
57631         if (text$$1) {
57632             // pseudo markdown bold text hack
57633             var parts = text$$1.split('**');
57634             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
57635             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
57636
57637             var selection$$1 = tooltip
57638                 .classed('in', true)
57639                 .selectAll('.tooltip-inner')
57640                 .html(html$$1);
57641
57642             var dimensions = utilGetDimensions(selection$$1, true),
57643                 w = window.innerWidth,
57644                 h = window.innerHeight,
57645                 side, pos;
57646
57647             // trim box dimensions to just the portion that fits in the window..
57648             if (box.top + box.height > h) {
57649                 box.height -= (box.top + box.height - h);
57650             }
57651             if (box.left + box.width > w) {
57652                 box.width -= (box.left + box.width - w);
57653             }
57654
57655             // determine tooltip placement..
57656             if (box.top + box.height < Math.min(100, box.width + box.left)) {
57657                 side = 'bottom';
57658                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
57659
57660             } else if (box.left + box.width + 300 < w) {
57661                 side = 'right';
57662                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
57663
57664             } else if (box.left > 300) {
57665                 side = 'left';
57666                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
57667
57668             } else {
57669                 side = 'bottom';
57670                 pos = [box.left, box.top + box.height];
57671             }
57672
57673             pos = [
57674                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
57675                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
57676             ];
57677
57678             if (duration !== 0 || !tooltip.classed(side)) {
57679                 tooltip.call(uiToggle(true));
57680             }
57681
57682             tooltip
57683                 .style('top', pos[1] + 'px')
57684                 .style('left', pos[0] + 'px')
57685                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
57686
57687         } else {
57688             tooltip.call(uiToggle(false));
57689         }
57690     };
57691
57692
57693     curtain.cut = function(datum, duration) {
57694         darkness.datum(datum)
57695             .interrupt();
57696
57697         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
57698             .attr('d', function(d) {
57699                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
57700                     window.innerWidth + ',' + window.innerHeight + 'L' +
57701                     window.innerWidth + ',0 Z';
57702
57703                 if (!d) return string;
57704                 return string + 'M' +
57705                     d.left + ',' + d.top + 'L' +
57706                     d.left + ',' + (d.top + d.height) + 'L' +
57707                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
57708                     (d.left + d.width) + ',' + (d.top) + 'Z';
57709
57710             });
57711     };
57712
57713
57714     curtain.remove = function() {
57715         surface.remove();
57716         tooltip.remove();
57717     };
57718
57719
57720     return utilRebind(curtain, dispatch$$1, 'on');
57721 }
57722
57723 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"]}};
57724
57725 function pointBox(point, context) {
57726     var rect = context.surfaceRect();
57727     point = context.projection(point);
57728     return {
57729         left: point[0] + rect.left - 30,
57730         top: point[1] + rect.top - 50,
57731         width: 60,
57732         height: 70
57733      };
57734 }
57735
57736
57737 function pad$1(box, padding, context) {
57738     if (box instanceof Array) {
57739         var rect = context.surfaceRect();
57740         box = context.projection(box);
57741         box = {
57742             left: box[0] + rect.left,
57743             top: box[1] + rect.top
57744         };
57745     }
57746     return {
57747         left: box.left - padding,
57748         top: box.top - padding,
57749         width: (box.width || 0) + 2 * padding,
57750         height: (box.width || 0) + 2 * padding
57751     };
57752 }
57753
57754
57755 function icon(name, svgklass) {
57756     return '<svg class="icon ' + (svgklass || '') + '">' +
57757          '<use xlink:href="' + name + '"></use></svg>';
57758  }
57759
57760 function uiIntroNavigation(context, reveal) {
57761     var dispatch$$1 = dispatch('done'),
57762         timeouts = [];
57763
57764     var step = {
57765         title: 'intro.navigation.title'
57766     };
57767
57768
57769     function set$$1(f, t$$1) {
57770         timeouts.push(window.setTimeout(f, t$$1));
57771     }
57772
57773
57774     function eventCancel() {
57775         event.stopPropagation();
57776         event.preventDefault();
57777     }
57778
57779
57780     step.enter = function() {
57781         var rect = context.surfaceRect(),
57782             map$$1 = {
57783                 left: rect.left + 10,
57784                 top: rect.top + 70,
57785                 width: rect.width - 70,
57786                 height: rect.height - 170
57787             };
57788
57789         context.map().centerZoom([-85.63591, 41.94285], 19);
57790
57791         reveal(map$$1, t('intro.navigation.drag'));
57792
57793         context.map().on('move.intro', lodash.debounce(function() {
57794             context.map().on('move.intro', null);
57795             townhall();
57796             context.on('enter.intro', inspectTownHall);
57797         }, 400));
57798
57799
57800         function townhall() {
57801             var hall = [-85.63645945147184, 41.942986488012565];
57802             var point = context.projection(hall);
57803
57804             if (point[0] < 0 || point[0] > rect.width ||
57805                 point[1] < 0 || point[1] > rect.height) {
57806                 context.map().center(hall);
57807             }
57808
57809             var box = pointBox(hall, context);
57810             reveal(box, t('intro.navigation.select'));
57811
57812             context.map().on('move.intro', function() {
57813                 var box = pointBox(hall, context);
57814                 reveal(box, t('intro.navigation.select'), {duration: 0});
57815             });
57816         }
57817
57818
57819         function inspectTownHall(mode) {
57820             if (mode.id !== 'select') return;
57821             context.on('enter.intro', null);
57822             context.map().on('move.intro', null);
57823             set$$1(function() {
57824                 reveal('.entity-editor-pane',
57825                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
57826                 context.on('exit.intro', streetSearch);
57827             }, 700);
57828         }
57829
57830
57831         function streetSearch() {
57832             context.on('exit.intro', null);
57833             reveal('.search-header input',
57834                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
57835             select('.search-header input')
57836                 .on('keyup.intro', searchResult);
57837         }
57838
57839
57840         function searchResult() {
57841             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
57842                 firstName = first.select('.entity-name'),
57843                 name = t('intro.graph.spring_st');
57844
57845             if (!firstName.empty() && firstName.text() === name) {
57846                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
57847                 context.on('exit.intro', selectedStreet);
57848                 select('.search-header input')
57849                     .on('keydown.intro', eventCancel, true)
57850                     .on('keyup.intro', null);
57851             }
57852         }
57853
57854
57855         function selectedStreet() {
57856             var springSt = [-85.63585099140167, 41.942506848938926];
57857             context.map().center(springSt);
57858             context.on('exit.intro', function() {
57859                 dispatch$$1.call('done');
57860             });
57861
57862             set$$1(function() {
57863                 reveal('.entity-editor-pane',
57864                     t('intro.navigation.chosen', {
57865                         name: t('intro.graph.spring_st'),
57866                         button: icon('#icon-close', 'pre-text')
57867                     }));
57868             }, 400);
57869         }
57870     };
57871
57872
57873     step.exit = function() {
57874         timeouts.forEach(window.clearTimeout);
57875         context.map().on('move.intro', null);
57876         context.on('enter.intro', null);
57877         context.on('exit.intro', null);
57878         select('.search-header input')
57879             .on('keydown.intro', null)
57880             .on('keyup.intro', null);
57881     };
57882
57883
57884     return utilRebind(step, dispatch$$1, 'on');
57885 }
57886
57887 function uiIntroPoint(context, reveal) {
57888     var dispatch$$1 = dispatch('done'),
57889         timeouts = [];
57890
57891     var step = {
57892         title: 'intro.points.title'
57893     };
57894
57895
57896     function setTimeout(f, t$$1) {
57897         timeouts.push(window.setTimeout(f, t$$1));
57898     }
57899
57900
57901     function eventCancel() {
57902         event.stopPropagation();
57903         event.preventDefault();
57904     }
57905
57906
57907     step.enter = function() {
57908         context.map().centerZoom([-85.63279, 41.94394], 19);
57909         reveal('button.add-point',
57910             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
57911             { tooltipClass: 'intro-points-add' });
57912
57913         var corner = [-85.632481,41.944094];
57914
57915         context.on('enter.intro', addPoint);
57916
57917
57918         function addPoint(mode) {
57919             if (mode.id !== 'add-point') return;
57920             context.on('enter.intro', enterSelect);
57921
57922             var pointBox$$1 = pad$1(corner, 150, context);
57923             reveal(pointBox$$1, t('intro.points.place'));
57924
57925             context.map().on('move.intro', function() {
57926                 pointBox$$1 = pad$1(corner, 150, context);
57927                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
57928             });
57929         }
57930
57931
57932         function enterSelect(mode) {
57933             if (mode.id !== 'select') return;
57934             context.map().on('move.intro', null);
57935             context.on('enter.intro', null);
57936
57937             setTimeout(function() {
57938                 reveal('.preset-search-input',
57939                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
57940                 select('.preset-search-input').on('keyup.intro', keySearch);
57941             }, 500);
57942         }
57943
57944
57945         function keySearch() {
57946             var first = select('.preset-list-item:first-child');
57947             if (first.classed('preset-amenity-cafe')) {
57948                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
57949                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57950                 select('.preset-search-input')
57951                     .on('keydown.intro', eventCancel, true)
57952                     .on('keyup.intro', null);
57953             }
57954         }
57955
57956
57957         function selectedPreset() {
57958             setTimeout(function() {
57959                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
57960                 context.history().on('change.intro', closeEditor);
57961                 context.on('exit.intro', selectPoint);
57962             }, 400);
57963         }
57964
57965
57966         function closeEditor() {
57967             select('.preset-search-input').on('keydown.intro', null);
57968             context.history().on('change.intro', null);
57969             reveal('.entity-editor-pane',
57970                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
57971         }
57972
57973
57974         function selectPoint() {
57975             context.on('exit.intro', null);
57976             context.history().on('change.intro', null);
57977             context.on('enter.intro', enterReselect);
57978
57979             var pointBox$$1 = pad$1(corner, 150, context);
57980             reveal(pointBox$$1, t('intro.points.reselect'));
57981
57982             context.map().on('move.intro', function() {
57983                 pointBox$$1 = pad$1(corner, 150, context);
57984                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
57985             });
57986         }
57987
57988
57989         function enterReselect(mode) {
57990             if (mode.id !== 'select') return;
57991             context.map().on('move.intro', null);
57992             context.on('enter.intro', null);
57993
57994             setTimeout(function() {
57995                 reveal('.entity-editor-pane',
57996                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
57997                 context.on('exit.intro', deletePoint);
57998             }, 500);
57999         }
58000
58001
58002         function deletePoint() {
58003             context.on('exit.intro', null);
58004             context.on('enter.intro', enterDelete);
58005
58006             var pointBox$$1 = pad$1(corner, 150, context);
58007             reveal(pointBox$$1, t('intro.points.reselect_delete'));
58008
58009             context.map().on('move.intro', function() {
58010                 pointBox$$1 = pad$1(corner, 150, context);
58011                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
58012             });
58013         }
58014
58015
58016         function enterDelete(mode) {
58017             if (mode.id !== 'select') return;
58018             context.map().on('move.intro', null);
58019             context.on('enter.intro', null);
58020             context.on('exit.intro', deletePoint);
58021             context.map().on('move.intro', deletePoint);
58022             context.history().on('change.intro', deleted);
58023
58024             setTimeout(function() {
58025                 var node = select('.radial-menu-item-delete').node();
58026                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
58027                 reveal(pointBox$$1,
58028                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
58029             }, 300);
58030         }
58031
58032
58033         function deleted(changed) {
58034             if (changed.deleted().length) {
58035                 dispatch$$1.call('done');
58036             }
58037         }
58038
58039     };
58040
58041
58042     step.exit = function() {
58043         timeouts.forEach(window.clearTimeout);
58044         context.on('exit.intro', null);
58045         context.on('enter.intro', null);
58046         context.map().on('move.intro', null);
58047         context.history().on('change.intro', null);
58048         select('.preset-search-input')
58049             .on('keyup.intro', null)
58050             .on('keydown.intro', null);
58051     };
58052
58053     return utilRebind(step, dispatch$$1, 'on');
58054 }
58055
58056 function uiIntroArea(context, reveal) {
58057     var dispatch$$1 = dispatch('done'),
58058         timeout$$1;
58059
58060     var step = {
58061         title: 'intro.areas.title'
58062     };
58063
58064
58065     step.enter = function() {
58066         var playground = [-85.63552, 41.94159],
58067             corner = [-85.63565411045074, 41.9417715536927];
58068         context.map().centerZoom(playground, 19);
58069         reveal('button.add-area',
58070             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
58071             { tooltipClass: 'intro-areas-add' });
58072
58073         context.on('enter.intro', addArea);
58074
58075
58076         function addArea(mode) {
58077             if (mode.id !== 'add-area') return;
58078             context.on('enter.intro', drawArea);
58079
58080             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
58081             var pointBox$$1 = pad$1(corner, padding, context);
58082             reveal(pointBox$$1, t('intro.areas.corner'));
58083
58084             context.map().on('move.intro', function() {
58085                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
58086                 pointBox$$1 = pad$1(corner, padding, context);
58087                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
58088             });
58089         }
58090
58091
58092         function drawArea(mode) {
58093             if (mode.id !== 'draw-area') return;
58094             context.on('enter.intro', enterSelect);
58095
58096             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
58097             var pointBox$$1 = pad$1(playground, padding, context);
58098             reveal(pointBox$$1, t('intro.areas.place'));
58099
58100             context.map().on('move.intro', function() {
58101                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
58102                 pointBox$$1 = pad$1(playground, padding, context);
58103                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
58104             });
58105         }
58106
58107
58108         function enterSelect(mode) {
58109             if (mode.id !== 'select') return;
58110             context.map().on('move.intro', null);
58111             context.on('enter.intro', null);
58112
58113             timeout$$1 = setTimeout(function() {
58114                 reveal('.preset-search-input',
58115                     t('intro.areas.search',
58116                     { name: context.presets().item('leisure/playground').name() }));
58117                 select('.preset-search-input').on('keyup.intro', keySearch);
58118             }, 500);
58119         }
58120
58121
58122         function keySearch() {
58123             var first = select('.preset-list-item:first-child');
58124             if (first.classed('preset-leisure-playground')) {
58125                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
58126                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
58127                 select('.preset-search-input').on('keyup.intro', null);
58128             }
58129         }
58130
58131
58132         function selectedPreset() {
58133             reveal('.pane',
58134                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
58135             context.on('exit.intro', function() {
58136                 dispatch$$1.call('done');
58137             });
58138         }
58139     };
58140
58141
58142     step.exit = function() {
58143         window.clearTimeout(timeout$$1);
58144         context.on('enter.intro', null);
58145         context.on('exit.intro', null);
58146         context.history().on('change.intro', null);
58147         context.map().on('move.intro', null);
58148         select('.preset-search-input').on('keyup.intro', null);
58149     };
58150
58151
58152     return utilRebind(step, dispatch$$1, 'on');
58153 }
58154
58155 function uiIntroLine(context, reveal) {
58156     var dispatch$$1 = dispatch('done'),
58157         timeouts = [],
58158         centroid = [-85.62830, 41.95699],
58159         midpoint = [-85.62975395449628, 41.95787501510204],
58160         start = [-85.6297754121684, 41.95805253325314],
58161         intersection = [-85.62974496187628, 41.95742515554585],
58162         targetId = 'w17965351',
58163         drawId = null;
58164
58165
58166     var step = {
58167         title: 'intro.lines.title'
58168     };
58169
58170
58171     function timeout$$1(f, t$$1) {
58172         timeouts.push(window.setTimeout(f, t$$1));
58173     }
58174
58175
58176     function eventCancel() {
58177         event.stopPropagation();
58178         event.preventDefault();
58179     }
58180
58181
58182     step.enter = function() {
58183         context.map().centerZoom(start, 18);
58184         reveal('button.add-line',
58185             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
58186             { tooltipClass: 'intro-lines-add' });
58187
58188         context.on('enter.intro', addLine);
58189
58190
58191         function addLine(mode) {
58192             if (mode.id !== 'add-line') return;
58193             drawId = null;
58194             context.on('enter.intro', drawLine);
58195
58196             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
58197             var pointBox$$1 = pad$1(start, padding, context);
58198             reveal(pointBox$$1, t('intro.lines.start'));
58199
58200             context.map().on('move.intro', function() {
58201                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
58202                 pointBox$$1 = pad$1(start, padding, context);
58203                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
58204             });
58205         }
58206
58207
58208         function drawLine(mode) {
58209             if (mode.id !== 'draw-line') return;
58210             drawId = mode.selectedIDs()[0];
58211             context.history().on('change.intro', checkIntersection);
58212             context.on('enter.intro', retry);
58213
58214             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
58215             var pointBox$$1 = pad$1(midpoint, padding, context);
58216             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
58217
58218             context.map().on('move.intro', function() {
58219                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
58220                 pointBox$$1 = pad$1(midpoint, padding, context);
58221                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
58222             });
58223         }
58224
58225
58226         // ended line before creating intersection
58227         function retry(mode) {
58228             if (mode.id !== 'select') return;
58229             context.history().on('change.intro', null);
58230             var pointBox$$1 = pad$1(intersection, 30, context);
58231             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
58232             select(window).on('mousedown.intro', eventCancel, true);
58233
58234             timeout$$1(step.restart, 3000);
58235         }
58236
58237
58238         function checkIntersection() {
58239
58240             function joinedTargetWay() {
58241                 var drawEntity = drawId && context.hasEntity(drawId);
58242                 if (!drawEntity) {
58243                     step.restart();
58244                     return false;
58245                 }
58246
58247                 var drawNodes = context.graph().childNodes(drawEntity);
58248                 return lodash.some(drawNodes, function(node) {
58249                     return lodash.some(context.graph().parentWays(node), function(parent) {
58250                         return parent.id === targetId;
58251                     });
58252                 });
58253             }
58254
58255             if (joinedTargetWay()) {
58256                 context.history().on('change.intro', null);
58257                 context.on('enter.intro', enterSelect);
58258
58259                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
58260                 var pointBox$$1 = pad$1(centroid, padding, context);
58261                 reveal(pointBox$$1, t('intro.lines.finish'));
58262
58263                 context.map().on('move.intro', function() {
58264                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
58265                     pointBox$$1 = pad$1(centroid, padding, context);
58266                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
58267                 });
58268             }
58269         }
58270
58271
58272         function enterSelect(mode) {
58273             if (mode.id !== 'select') return;
58274             context.map().on('move.intro', null);
58275             context.on('enter.intro', null);
58276             select('#curtain').style('pointer-events', 'all');
58277             presetCategory();
58278         }
58279
58280
58281         function presetCategory() {
58282             timeout$$1(function() {
58283                 select('#curtain').style('pointer-events', 'none');
58284                 var road = select('.preset-category-road .preset-list-button');
58285                 reveal(road.node(), t('intro.lines.road'));
58286                 utilBindOnce(road, 'click.intro', roadCategory);
58287             }, 500);
58288         }
58289
58290
58291         function roadCategory() {
58292             timeout$$1(function() {
58293                 var grid = select('.subgrid');
58294                 reveal(grid.node(), t('intro.lines.residential'));
58295                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
58296                     'click.intro', retryPreset);
58297                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
58298                     'click.intro', roadDetails);
58299             }, 500);
58300         }
58301
58302
58303         // selected wrong road type
58304         function retryPreset() {
58305             timeout$$1(function() {
58306                 var preset = select('.entity-editor-pane .preset-list-button');
58307                 reveal(preset.node(), t('intro.lines.wrong_preset'));
58308                 utilBindOnce(preset, 'click.intro', presetCategory);
58309             }, 500);
58310         }
58311
58312
58313         function roadDetails() {
58314             reveal('.pane',
58315                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
58316             context.on('exit.intro', function() {
58317                 dispatch$$1.call('done');
58318             });
58319         }
58320     };
58321
58322
58323     step.restart = function() {
58324         step.exit();
58325         step.enter();
58326     };
58327
58328
58329     step.exit = function() {
58330         select(window).on('mousedown.intro', null, true);
58331         select('#curtain').style('pointer-events', 'none');
58332         timeouts.forEach(window.clearTimeout);
58333         context.on('enter.intro', null);
58334         context.on('exit.intro', null);
58335         context.map().on('move.intro', null);
58336         context.history().on('change.intro', null);
58337         if (drawId) {
58338             context.replace(actionDeleteMultiple([drawId]));
58339             drawId = null;
58340         }
58341     };
58342
58343     return utilRebind(step, dispatch$$1, 'on');
58344 }
58345
58346 function uiIntroStartEditing(context, reveal) {
58347     var dispatch$$1 = dispatch('done', 'startEditing'),
58348         modalSelection,
58349         timeouts = [];
58350
58351     var step = {
58352         title: 'intro.startediting.title'
58353     };
58354
58355
58356     function timeout$$1(f, t$$1) {
58357         timeouts.push(window.setTimeout(f, t$$1));
58358     }
58359
58360
58361     step.enter = function() {
58362         reveal('.map-control.help-control',
58363             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
58364
58365         timeout$$1(function() {
58366             reveal('#bar button.save', t('intro.startediting.save'));
58367         }, 5000);
58368
58369         timeout$$1(function() {
58370             reveal('#surface');
58371         }, 10000);
58372
58373         timeout$$1(function() {
58374             modalSelection = uiModal(context.container());
58375
58376             modalSelection.select('.modal')
58377                 .attr('class', 'modal-splash modal col6');
58378
58379             modalSelection.selectAll('.close').remove();
58380
58381             var startbutton = modalSelection.select('.content')
58382                 .attr('class', 'fillL')
58383                 .append('button')
58384                     .attr('class', 'modal-section huge-modal-button')
58385                     .on('click', function() {
58386                         modalSelection.remove();
58387                     });
58388
58389                 startbutton
58390                     .append('div')
58391                     .attr('class','illustration');
58392
58393                 startbutton
58394                     .append('h2')
58395                     .text(t('intro.startediting.start'));
58396
58397             dispatch$$1.call('startEditing');
58398         }, 10500);
58399     };
58400
58401
58402     step.exit = function() {
58403         if (modalSelection) { modalSelection.remove(); }
58404         timeouts.forEach(window.clearTimeout);
58405     };
58406
58407
58408     return utilRebind(step, dispatch$$1, 'on');
58409 }
58410
58411 var sampleIntros = {
58412     navigation: uiIntroNavigation,
58413     point: uiIntroPoint,
58414     area: uiIntroArea,
58415     line: uiIntroLine,
58416     startEditing: uiIntroStartEditing
58417 };
58418
58419
58420 function uiIntro(context) {
58421     var step;
58422
58423     function localizedName(id) {
58424         var features = {
58425             n2140018997: 'city_hall',
58426             n367813436: 'fire_department',
58427             w203988286: 'memory_isle_park',
58428             w203972937: 'riverwalk_trail',
58429             w203972938: 'riverwalk_trail',
58430             w203972940: 'riverwalk_trail',
58431             w41785752: 'w_michigan_ave',
58432             w134150789: 'w_michigan_ave',
58433             w134150795: 'w_michigan_ave',
58434             w134150800: 'w_michigan_ave',
58435             w134150811: 'w_michigan_ave',
58436             w134150802: 'e_michigan_ave',
58437             w134150836: 'e_michigan_ave',
58438             w41074896: 'e_michigan_ave',
58439             w17965834: 'spring_st',
58440             w203986457: 'scidmore_park',
58441             w203049587: 'petting_zoo',
58442             w17967397: 'n_andrews_st',
58443             w17967315: 's_andrews_st',
58444             w17967326: 'n_constantine_st',
58445             w17966400: 's_constantine_st',
58446             w170848823: 'rocky_river',
58447             w170848824: 'rocky_river',
58448             w170848331: 'rocky_river',
58449             w17967752: 'railroad_dr',
58450             w17965998: 'conrail_rr',
58451             w134150845: 'conrail_rr',
58452             w170989131: 'st_joseph_river',
58453             w143497377: 'n_main_st',
58454             w134150801: 's_main_st',
58455             w134150830: 's_main_st',
58456             w17966462: 's_main_st',
58457             w17967734: 'water_st',
58458             w17964996: 'foster_st',
58459             w170848330: 'portage_river',
58460             w17965351: 'flower_st',
58461             w17965502: 'elm_st',
58462             w17965402: 'walnut_st',
58463             w17964793: 'morris_ave',
58464             w17967444: 'east_st',
58465             w17966984: 'portage_ave'
58466         };
58467
58468         return features[id] && t('intro.graph.' + features[id]);
58469     }
58470
58471
58472     var introGraph = {};
58473
58474     for (var key in dataIntroGraph) {
58475         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
58476         var name = localizedName(key);
58477         if (name) {
58478             introGraph[key].tags.name = name;
58479         }
58480     }
58481
58482
58483     function intro(selection$$1) {
58484         context.enter(modeBrowse(context));
58485
58486         // Save current map state
58487         var history = context.history().toJSON(),
58488             hash = window.location.hash,
58489             center = context.map().center(),
58490             zoom$$1 = context.map().zoom(),
58491             background = context.background().baseLayerSource(),
58492             opacity = selectAll('#map .layer-background').style('opacity'),
58493             loadedTiles = context.connection().loadedTiles(),
58494             baseEntities = context.history().graph().base().entities;
58495
58496         // Block saving
58497         context.inIntro(true);
58498
58499         // Load semi-real data used in intro
58500         context.connection().toggle(false).reset();
58501         context.history().reset();
58502
58503         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
58504         context.background().bing();
58505
58506         selectAll('#map .layer-background').style('opacity', 1);
58507
58508         var curtain = d3curtain();
58509         selection$$1.call(curtain);
58510
58511
58512         function reveal(box, text$$1, options) {
58513             options = options || {};
58514             curtain.reveal(box,
58515                 text$$1 || '',
58516                 options.tooltipClass || '',
58517                 options.duration
58518             );
58519         }
58520
58521         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
58522             var s = sampleIntros[step](context, reveal)
58523                 .on('done', function() {
58524                     entered.filter(function(d) {
58525                         return d.title === s.title;
58526                     }).classed('finished', true);
58527                     enter(steps[i + 1]);
58528                 });
58529             return s;
58530         });
58531
58532         steps[steps.length - 1].on('startEditing', function() {
58533             curtain.remove();
58534             navwrap.remove();
58535             selectAll('#map .layer-background').style('opacity', opacity);
58536             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
58537             context.history().reset().merge(values(baseEntities));
58538             context.background().baseLayerSource(background);
58539             if (history) context.history().fromJSON(history, false);
58540             context.map().centerZoom(center, zoom$$1);
58541             window.location.replace(hash);
58542             context.inIntro(false);
58543         });
58544
58545         var navwrap = selection$$1
58546             .append('div')
58547             .attr('class', 'intro-nav-wrap fillD');
58548
58549         var buttonwrap = navwrap
58550             .append('div')
58551             .attr('class', 'joined')
58552             .selectAll('button.step');
58553
58554         var entered = buttonwrap
58555             .data(steps)
58556             .enter()
58557             .append('button')
58558             .attr('class', 'step')
58559             .on('click', enter);
58560
58561         entered
58562             .append('label')
58563             .text(function(d) { return t(d.title); });
58564
58565         entered
58566             .append('span')
58567             .attr('class', 'status')
58568             .text(' - ' + t('intro.done'));
58569
58570         enter(steps[0]);
58571
58572
58573         function enter(newStep) {
58574             if (step) { step.exit(); }
58575
58576             context.enter(modeBrowse(context));
58577
58578             step = newStep;
58579             step.enter();
58580
58581             entered.classed('active', function(d) {
58582                 return d.title === step.title;
58583             });
58584         }
58585
58586     }
58587
58588
58589     return intro;
58590 }
58591
58592 function uiHelp(context) {
58593     var key = 'H';
58594
58595     var docKeys = [
58596         'help.help',
58597         'help.editing_saving',
58598         'help.roads',
58599         'help.gps',
58600         'help.imagery',
58601         'help.addresses',
58602         'help.inspector',
58603         'help.buildings',
58604         'help.relations'];
58605
58606     var docs = docKeys.map(function(key) {
58607         var text$$1 = t(key);
58608         return {
58609             title: text$$1.split('\n')[0].replace('#', '').trim(),
58610             html: marked(text$$1.split('\n').slice(1).join('\n'))
58611         };
58612     });
58613
58614
58615     function help(selection$$1) {
58616
58617         function hide() {
58618             setVisible(false);
58619         }
58620
58621
58622         function toggle() {
58623             if (event) event.preventDefault();
58624             tooltipBehavior.hide(button);
58625             setVisible(!button.classed('active'));
58626         }
58627
58628
58629         function setVisible(show) {
58630             if (show !== shown) {
58631                 button.classed('active', show);
58632                 shown = show;
58633
58634                 if (show) {
58635                     selection$$1.on('mousedown.help-inside', function() {
58636                         return event.stopPropagation();
58637                     });
58638                     pane.style('display', 'block')
58639                         .style('right', '-500px')
58640                         .transition()
58641                         .duration(200)
58642                         .style('right', '0px');
58643                 } else {
58644                     pane.style('right', '0px')
58645                         .transition()
58646                         .duration(200)
58647                         .style('right', '-500px')
58648                         .on('end', function() {
58649                             select(this).style('display', 'none');
58650                         });
58651                     selection$$1.on('mousedown.help-inside', null);
58652                 }
58653             }
58654         }
58655
58656
58657         function clickHelp(d, i) {
58658             var rtl = (textDirection === 'rtl');
58659             pane.property('scrollTop', 0);
58660             doctitle.html(d.title);
58661
58662             body.html(d.html);
58663             body.selectAll('a')
58664                 .attr('target', '_blank');
58665             menuItems.classed('selected', function(m) {
58666                 return m.title === d.title;
58667             });
58668
58669             nav.html('');
58670             if (rtl) {
58671                 nav.call(drawNext).call(drawPrevious);
58672             } else {
58673                 nav.call(drawPrevious).call(drawNext);
58674             }
58675
58676
58677             function drawNext(selection$$1) {
58678                 if (i < docs.length - 1) {
58679                     var nextLink = selection$$1
58680                         .append('a')
58681                         .attr('class', 'next')
58682                         .on('click', function() {
58683                             clickHelp(docs[i + 1], i + 1);
58684                         });
58685
58686                     nextLink
58687                         .append('span')
58688                         .text(docs[i + 1].title)
58689                         .call(svgIcon((rtl ? '#icon-backward' : '#icon-forward'), 'inline'));
58690                 }
58691             }
58692
58693
58694             function drawPrevious(selection$$1) {
58695                 if (i > 0) {
58696                     var prevLink = selection$$1
58697                         .append('a')
58698                         .attr('class', 'previous')
58699                         .on('click', function() {
58700                             clickHelp(docs[i - 1], i - 1);
58701                         });
58702
58703                     prevLink
58704                         .call(svgIcon((rtl ? '#icon-forward' : '#icon-backward'), 'inline'))
58705                         .append('span')
58706                         .text(docs[i - 1].title);
58707                 }
58708             }
58709         }
58710
58711
58712         function clickWalkthrough() {
58713             select(document.body).call(uiIntro(context));
58714             setVisible(false);
58715         }
58716
58717
58718         var pane = selection$$1.append('div')
58719                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
58720             tooltipBehavior = tooltip()
58721                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58722                 .html(true)
58723                 .title(uiTooltipHtml(t('help.title'), key)),
58724             button = selection$$1.append('button')
58725                 .attr('tabindex', -1)
58726                 .on('click', toggle)
58727                 .call(svgIcon('#icon-help', 'light'))
58728                 .call(tooltipBehavior),
58729             shown = false;
58730
58731
58732         var toc = pane.append('ul')
58733             .attr('class', 'toc');
58734
58735         var menuItems = toc.selectAll('li')
58736             .data(docs)
58737             .enter()
58738             .append('li')
58739             .append('a')
58740             .html(function(d) { return d.title; })
58741             .on('click', clickHelp);
58742
58743         toc.append('li')
58744             .attr('class','walkthrough')
58745             .append('a')
58746             .text(t('splash.walkthrough'))
58747             .on('click', clickWalkthrough);
58748
58749         var content = pane.append('div')
58750             .attr('class', 'left-content');
58751
58752         var doctitle = content.append('h2')
58753             .text(t('help.title'));
58754
58755         var body = content.append('div')
58756             .attr('class', 'body');
58757
58758         var nav = content.append('div')
58759             .attr('class', 'nav');
58760
58761         clickHelp(docs[0], 0);
58762
58763         var keybinding = d3keybinding('help')
58764             .on(key, toggle)
58765             .on('B', hide)
58766             .on('F', hide);
58767
58768         select(document)
58769             .call(keybinding);
58770
58771         context.surface().on('mousedown.help-outside', hide);
58772         context.container().on('mousedown.help-outside', hide);
58773     }
58774
58775     return help;
58776 }
58777
58778 function uiInfo(context) {
58779     var key = uiCmd('⌘I'),
58780         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58781         isHidden = true;
58782
58783
58784     function info(selection$$1) {
58785
58786         function radiansToMeters(r) {
58787             // using WGS84 authalic radius (6371007.1809 m)
58788             return r * 6371007.1809;
58789         }
58790
58791         function steradiansToSqmeters(r) {
58792             // http://gis.stackexchange.com/a/124857/40446
58793             return r / (4 * Math.PI) * 510065621724000;
58794         }
58795
58796
58797         function toLineString(feature) {
58798             if (feature.type === 'LineString') return feature;
58799
58800             var result = { type: 'LineString', coordinates: [] };
58801             if (feature.type === 'Polygon') {
58802                 result.coordinates = feature.coordinates[0];
58803             } else if (feature.type === 'MultiPolygon') {
58804                 result.coordinates = feature.coordinates[0][0];
58805             }
58806
58807             return result;
58808         }
58809
58810
58811         function displayLength(m) {
58812             var d = m * (isImperial ? 3.28084 : 1),
58813                 p, unit;
58814
58815             if (isImperial) {
58816                 if (d >= 5280) {
58817                     d /= 5280;
58818                     unit = 'mi';
58819                 } else {
58820                     unit = 'ft';
58821                 }
58822             } else {
58823                 if (d >= 1000) {
58824                     d /= 1000;
58825                     unit = 'km';
58826                 } else {
58827                     unit = 'm';
58828                 }
58829             }
58830
58831             // drop unnecessary precision
58832             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
58833
58834             return String(d.toFixed(p)) + ' ' + unit;
58835         }
58836
58837
58838         function displayArea(m2) {
58839             var d = m2 * (isImperial ? 10.7639111056 : 1),
58840                 d1, d2, p1, p2, unit1, unit2;
58841
58842             if (isImperial) {
58843                 if (d >= 6969600) {     // > 0.25mi² show mi²
58844                     d1 = d / 27878400;
58845                     unit1 = 'mi²';
58846                 } else {
58847                     d1 = d;
58848                     unit1 = 'ft²';
58849                 }
58850
58851                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
58852                     d2 = d / 43560;
58853                     unit2 = 'ac';
58854                 }
58855
58856             } else {
58857                 if (d >= 250000) {    // > 0.25km² show km²
58858                     d1 = d / 1000000;
58859                     unit1 = 'km²';
58860                 } else {
58861                     d1 = d;
58862                     unit1 = 'm²';
58863                 }
58864
58865                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
58866                     d2 = d / 10000;
58867                     unit2 = 'ha';
58868                 }
58869             }
58870
58871             // drop unnecessary precision
58872             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
58873             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
58874
58875             return String(d1.toFixed(p1)) + ' ' + unit1 +
58876                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
58877         }
58878
58879
58880         function redraw() {
58881             if (isHidden) return;
58882
58883             var resolver = context.graph(),
58884                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
58885                 singular = selected.length === 1 ? selected[0] : null,
58886                 extent$$1 = geoExtent$$1(),
58887                 entity;
58888
58889             wrap.html('');
58890             wrap.append('h4')
58891                 .attr('class', 'infobox-heading fillD')
58892                 .text(singular || t('infobox.selected', { n: selected.length }));
58893
58894             if (!selected.length) return;
58895
58896             var center;
58897             for (var i = 0; i < selected.length; i++) {
58898                 entity = context.entity(selected[i]);
58899                 extent$$1._extend(entity.extent(resolver));
58900             }
58901             center = extent$$1.center();
58902
58903
58904             var list = wrap.append('ul');
58905
58906             // multiple features, just display extent center..
58907             if (!singular) {
58908                 list.append('li')
58909                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58910                 return;
58911             }
58912
58913             // single feature, display details..
58914             if (!entity) return;
58915             var geometry = entity.geometry(resolver);
58916
58917             if (geometry === 'line' || geometry === 'area') {
58918                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
58919                     feature = entity.asGeoJSON(resolver),
58920                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
58921                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
58922                     centroid = d3GeoCentroid(feature);
58923
58924                 list.append('li')
58925                     .text(t('infobox.geometry') + ': ' +
58926                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
58927
58928                 if (closed) {
58929                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
58930                     list.append('li')
58931                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
58932                 }
58933
58934                 list.append('li')
58935                     .text(lengthLabel + ': ' + displayLength(length));
58936
58937                 list.append('li')
58938                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
58939
58940
58941                 var toggle  = isImperial ? 'imperial' : 'metric';
58942                 wrap.append('a')
58943                     .text(t('infobox.' + toggle))
58944                     .attr('href', '#')
58945                     .attr('class', 'button')
58946                     .on('click', function() {
58947                         event.preventDefault();
58948                         isImperial = !isImperial;
58949                         redraw();
58950                     });
58951
58952             } else {
58953                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
58954
58955                 list.append('li')
58956                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
58957
58958                 list.append('li')
58959                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58960             }
58961         }
58962
58963
58964         function toggle() {
58965             if (event) {
58966                 event.preventDefault();
58967             }
58968
58969             isHidden = !isHidden;
58970
58971             if (isHidden) {
58972                 wrap
58973                     .style('display', 'block')
58974                     .style('opacity', 1)
58975                     .transition()
58976                     .duration(200)
58977                     .style('opacity', 0)
58978                     .on('end', function() {
58979                         select(this).style('display', 'none');
58980                     });
58981             } else {
58982                 wrap
58983                     .style('display', 'block')
58984                     .style('opacity', 0)
58985                     .transition()
58986                     .duration(200)
58987                     .style('opacity', 1)
58988                     .on('end', function() {
58989                         redraw();
58990                     });
58991             }
58992         }
58993
58994
58995         var wrap = selection$$1.selectAll('.infobox')
58996             .data([0]);
58997
58998         wrap = wrap.enter()
58999             .append('div')
59000             .attr('class', 'infobox fillD2')
59001             .style('display', (isHidden ? 'none' : 'block'))
59002             .merge(wrap);
59003
59004         context.map()
59005             .on('drawn.info', redraw);
59006
59007         redraw();
59008
59009         var keybinding = d3keybinding('info')
59010             .on(key, toggle);
59011
59012         select(document)
59013             .call(keybinding);
59014     }
59015
59016     return info;
59017 }
59018
59019 function uiMapData(context) {
59020     var key = 'F',
59021         features = context.features().keys(),
59022         layers = context.layers(),
59023         fills = ['wireframe', 'partial', 'full'],
59024         fillDefault = context.storage('area-fill') || 'partial',
59025         fillSelected = fillDefault;
59026
59027
59028     function map_data(selection$$1) {
59029
59030         function showsFeature(d) {
59031             return context.features().enabled(d);
59032         }
59033
59034
59035         function autoHiddenFeature(d) {
59036             return context.features().autoHidden(d);
59037         }
59038
59039
59040         function clickFeature(d) {
59041             context.features().toggle(d);
59042             update();
59043         }
59044
59045
59046         function showsFill(d) {
59047             return fillSelected === d;
59048         }
59049
59050
59051         function setFill(d) {
59052             lodash.each(fills, function(opt) {
59053                 context.surface().classed('fill-' + opt, Boolean(opt === d));
59054             });
59055
59056             fillSelected = d;
59057             if (d !== 'wireframe') {
59058                 fillDefault = d;
59059                 context.storage('area-fill', d);
59060             }
59061             update();
59062         }
59063
59064
59065         function showsLayer(which) {
59066             var layer = layers.layer(which);
59067             if (layer) {
59068                 return layer.enabled();
59069             }
59070             return false;
59071         }
59072
59073
59074         function setLayer(which, enabled) {
59075             var layer = layers.layer(which);
59076             if (layer) {
59077                 layer.enabled(enabled);
59078                 update();
59079             }
59080         }
59081
59082
59083         function toggleLayer(which) {
59084             setLayer(which, !showsLayer(which));
59085         }
59086
59087
59088         function clickGpx() {
59089             toggleLayer('gpx');
59090         }
59091
59092
59093         function clickMapillaryImages() {
59094             toggleLayer('mapillary-images');
59095             if (!showsLayer('mapillary-images')) {
59096                 setLayer('mapillary-signs', false);
59097             }
59098         }
59099
59100
59101         function clickMapillarySigns() {
59102             toggleLayer('mapillary-signs');
59103         }
59104
59105
59106         function drawMapillaryItems(selection$$1) {
59107             var mapillaryImages = layers.layer('mapillary-images'),
59108                 mapillarySigns = layers.layer('mapillary-signs'),
59109                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
59110                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
59111                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
59112                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
59113
59114             var mapillaryList = selection$$1
59115                 .selectAll('.layer-list-mapillary')
59116                 .data([0]);
59117
59118             mapillaryList = mapillaryList.enter()
59119                 .append('ul')
59120                 .attr('class', 'layer-list layer-list-mapillary')
59121                 .merge(mapillaryList);
59122
59123
59124             var mapillaryImageLayerItem = mapillaryList
59125                 .selectAll('.list-item-mapillary-images')
59126                 .data(supportsMapillaryImages ? [0] : []);
59127
59128             mapillaryImageLayerItem.exit()
59129                 .remove();
59130
59131             var enterImages = mapillaryImageLayerItem.enter()
59132                 .append('li')
59133                 .attr('class', 'list-item-mapillary-images');
59134
59135             var labelImages = enterImages
59136                 .append('label')
59137                 .call(tooltip()
59138                     .title(t('mapillary_images.tooltip'))
59139                     .placement('top'));
59140
59141             labelImages
59142                 .append('input')
59143                 .attr('type', 'checkbox')
59144                 .on('change', clickMapillaryImages);
59145
59146             labelImages
59147                 .append('span')
59148                 .text(t('mapillary_images.title'));
59149
59150
59151             var mapillarySignLayerItem = mapillaryList
59152                 .selectAll('.list-item-mapillary-signs')
59153                 .data(supportsMapillarySigns ? [0] : []);
59154
59155             mapillarySignLayerItem.exit()
59156                 .remove();
59157
59158             var enterSigns = mapillarySignLayerItem.enter()
59159                 .append('li')
59160                 .attr('class', 'list-item-mapillary-signs');
59161
59162             var labelSigns = enterSigns
59163                 .append('label')
59164                 .call(tooltip()
59165                     .title(t('mapillary_signs.tooltip'))
59166                     .placement('top'));
59167
59168             labelSigns
59169                 .append('input')
59170                 .attr('type', 'checkbox')
59171                 .on('change', clickMapillarySigns);
59172
59173             labelSigns
59174                 .append('span')
59175                 .text(t('mapillary_signs.title'));
59176
59177
59178             // Updates
59179             mapillaryImageLayerItem = mapillaryImageLayerItem
59180                 .merge(enterImages);
59181
59182             mapillaryImageLayerItem
59183                 .classed('active', showsMapillaryImages)
59184                 .selectAll('input')
59185                 .property('checked', showsMapillaryImages);
59186
59187
59188             mapillarySignLayerItem = mapillarySignLayerItem
59189                 .merge(enterSigns);
59190
59191             mapillarySignLayerItem
59192                 .classed('active', showsMapillarySigns)
59193                 .selectAll('input')
59194                 .property('disabled', !showsMapillaryImages)
59195                 .property('checked', showsMapillarySigns);
59196
59197             mapillarySignLayerItem
59198                 .selectAll('label')
59199                 .classed('deemphasize', !showsMapillaryImages);
59200         }
59201
59202
59203         function drawGpxItem(selection$$1) {
59204             var gpx = layers.layer('gpx'),
59205                 hasGpx = gpx && gpx.hasGpx(),
59206                 showsGpx = hasGpx && gpx.enabled();
59207
59208             var gpxLayerItem = selection$$1
59209                 .selectAll('.layer-list-gpx')
59210                 .data(gpx ? [0] : []);
59211
59212             // Exit
59213             gpxLayerItem.exit()
59214                 .remove();
59215
59216             // Enter
59217             var enter = gpxLayerItem.enter()
59218                 .append('ul')
59219                 .attr('class', 'layer-list layer-list-gpx')
59220                 .append('li')
59221                 .classed('list-item-gpx', true);
59222
59223             enter
59224                 .append('button')
59225                 .attr('class', 'list-item-gpx-extent')
59226                 .call(tooltip()
59227                     .title(t('gpx.zoom'))
59228                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59229                 .on('click', function() {
59230                     event.preventDefault();
59231                     event.stopPropagation();
59232                     gpx.fitZoom();
59233                 })
59234                 .call(svgIcon('#icon-search'));
59235
59236             enter
59237                 .append('button')
59238                 .attr('class', 'list-item-gpx-browse')
59239                 .call(tooltip()
59240                     .title(t('gpx.browse'))
59241                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
59242                 .on('click', function() {
59243                     select(document.createElement('input'))
59244                         .attr('type', 'file')
59245                         .on('change', function() {
59246                             gpx.files(event.target.files);
59247                         })
59248                         .node().click();
59249                 })
59250                 .call(svgIcon('#icon-geolocate'));
59251
59252             var labelGpx = enter
59253                 .append('label')
59254                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
59255
59256             labelGpx
59257                 .append('input')
59258                 .attr('type', 'checkbox')
59259                 .on('change', clickGpx);
59260
59261             labelGpx
59262                 .append('span')
59263                 .text(t('gpx.local_layer'));
59264
59265
59266             // Update
59267             gpxLayerItem = gpxLayerItem
59268                 .merge(enter);
59269
59270             gpxLayerItem
59271                 .classed('active', showsGpx)
59272                 .selectAll('input')
59273                 .property('disabled', !hasGpx)
59274                 .property('checked', showsGpx);
59275
59276             gpxLayerItem
59277                 .selectAll('label')
59278                 .classed('deemphasize', !hasGpx);
59279         }
59280
59281
59282         function drawList(selection$$1, data, type, name, change, active$$1) {
59283             var items = selection$$1.selectAll('li')
59284                 .data(data);
59285
59286             // Exit
59287             items.exit()
59288                 .remove();
59289
59290             // Enter
59291             var enter = items.enter()
59292                 .append('li')
59293                 .attr('class', 'layer')
59294                 .call(tooltip()
59295                     .html(true)
59296                     .title(function(d) {
59297                         var tip = t(name + '.' + d + '.tooltip'),
59298                             key = (d === 'wireframe' ? 'W' : null);
59299
59300                         if (name === 'feature' && autoHiddenFeature(d)) {
59301                             tip += '<div>' + t('map_data.autohidden') + '</div>';
59302                         }
59303                         return uiTooltipHtml(tip, key);
59304                     })
59305                     .placement('top')
59306                 );
59307
59308             var label = enter
59309                 .append('label');
59310
59311             label
59312                 .append('input')
59313                 .attr('type', type)
59314                 .attr('name', name)
59315                 .on('change', change);
59316
59317             label
59318                 .append('span')
59319                 .text(function(d) { return t(name + '.' + d + '.description'); });
59320
59321             // Update
59322             items = items
59323                 .merge(enter);
59324
59325             items
59326                 .classed('active', active$$1)
59327                 .selectAll('input')
59328                 .property('checked', active$$1)
59329                 .property('indeterminate', function(d) {
59330                     return (name === 'feature' && autoHiddenFeature(d));
59331                 });
59332         }
59333
59334
59335         function update() {
59336             dataLayerContainer.call(drawMapillaryItems);
59337             dataLayerContainer.call(drawGpxItem);
59338
59339             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
59340             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
59341         }
59342
59343
59344         function hidePanel() {
59345             setVisible(false);
59346         }
59347
59348
59349         function togglePanel() {
59350             if (event) event.preventDefault();
59351             tooltipBehavior.hide(button);
59352             setVisible(!button.classed('active'));
59353         }
59354
59355
59356         function toggleWireframe() {
59357             if (event) {
59358                 event.preventDefault();
59359                 event.stopPropagation();
59360             }
59361             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
59362             context.map().pan([0,0]);  // trigger a redraw
59363         }
59364
59365
59366         function setVisible(show) {
59367             if (show !== shown) {
59368                 button.classed('active', show);
59369                 shown = show;
59370
59371                 if (show) {
59372                     update();
59373                     selection$$1.on('mousedown.map_data-inside', function() {
59374                         return event.stopPropagation();
59375                     });
59376                     content.style('display', 'block')
59377                         .style('right', '-300px')
59378                         .transition()
59379                         .duration(200)
59380                         .style('right', '0px');
59381                 } else {
59382                     content.style('display', 'block')
59383                         .style('right', '0px')
59384                         .transition()
59385                         .duration(200)
59386                         .style('right', '-300px')
59387                         .on('end', function() {
59388                             select(this).style('display', 'none');
59389                         });
59390                     selection$$1.on('mousedown.map_data-inside', null);
59391                 }
59392             }
59393         }
59394
59395
59396         var content = selection$$1
59397                 .append('div')
59398                 .attr('class', 'fillL map-overlay col3 content hide'),
59399             tooltipBehavior = tooltip()
59400                 .placement((textDirection === 'rtl') ? 'right' : 'left')
59401                 .html(true)
59402                 .title(uiTooltipHtml(t('map_data.description'), key)),
59403             button = selection$$1
59404                 .append('button')
59405                 .attr('tabindex', -1)
59406                 .on('click', togglePanel)
59407                 .call(svgIcon('#icon-data', 'light'))
59408                 .call(tooltipBehavior),
59409             shown = false;
59410
59411         content
59412             .append('h4')
59413             .text(t('map_data.title'));
59414
59415
59416         // data layers
59417         content
59418             .append('a')
59419             .text(t('map_data.data_layers'))
59420             .attr('href', '#')
59421             .classed('hide-toggle', true)
59422             .classed('expanded', true)
59423             .on('click', function() {
59424                 var exp = select(this).classed('expanded');
59425                 dataLayerContainer.style('display', exp ? 'none' : 'block');
59426                 select(this).classed('expanded', !exp);
59427                 event.preventDefault();
59428             });
59429
59430         var dataLayerContainer = content
59431             .append('div')
59432             .attr('class', 'data-data-layers')
59433             .style('display', 'block');
59434
59435
59436         // area fills
59437         content
59438             .append('a')
59439             .text(t('map_data.fill_area'))
59440             .attr('href', '#')
59441             .classed('hide-toggle', true)
59442             .classed('expanded', false)
59443             .on('click', function() {
59444                 var exp = select(this).classed('expanded');
59445                 fillContainer.style('display', exp ? 'none' : 'block');
59446                 select(this).classed('expanded', !exp);
59447                 event.preventDefault();
59448             });
59449
59450         var fillContainer = content
59451             .append('div')
59452             .attr('class', 'data-area-fills')
59453             .style('display', 'none');
59454
59455         var fillList = fillContainer
59456             .append('ul')
59457             .attr('class', 'layer-list layer-fill-list');
59458
59459
59460         // feature filters
59461         content
59462             .append('a')
59463             .text(t('map_data.map_features'))
59464             .attr('href', '#')
59465             .classed('hide-toggle', true)
59466             .classed('expanded', false)
59467             .on('click', function() {
59468                 var exp = select(this).classed('expanded');
59469                 featureContainer.style('display', exp ? 'none' : 'block');
59470                 select(this).classed('expanded', !exp);
59471                 event.preventDefault();
59472             });
59473
59474         var featureContainer = content
59475             .append('div')
59476             .attr('class', 'data-feature-filters')
59477             .style('display', 'none');
59478
59479         var featureList = featureContainer
59480             .append('ul')
59481             .attr('class', 'layer-list layer-feature-list');
59482
59483
59484         context.features()
59485             .on('change.map_data-update', update);
59486
59487         setFill(fillDefault);
59488
59489         var keybinding = d3keybinding('features')
59490             .on(key, togglePanel)
59491             .on('W', toggleWireframe)
59492             .on('B', hidePanel)
59493             .on('H', hidePanel);
59494
59495         select(document)
59496             .call(keybinding);
59497
59498         context.surface().on('mousedown.map_data-outside', hidePanel);
59499         context.container().on('mousedown.map_data-outside', hidePanel);
59500     }
59501
59502
59503     return map_data;
59504 }
59505
59506 function uiModes(context) {
59507     var modes = [
59508         modeAddPoint$$1(context),
59509         modeAddLine$$1(context),
59510         modeAddArea$$1(context)
59511     ];
59512
59513
59514     function editable() {
59515         return context.editable() && context.mode().id !== 'save';
59516     }
59517
59518
59519     return function(selection$$1) {
59520         var buttons = selection$$1.selectAll('button.add-button')
59521             .data(modes);
59522
59523         buttons = buttons.enter()
59524             .append('button')
59525             .attr('tabindex', -1)
59526             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
59527             .on('click.mode-buttons', function(mode) {
59528                 if (mode.id === context.mode().id) {
59529                     context.enter(modeBrowse(context));
59530                 } else {
59531                     context.enter(mode);
59532                 }
59533             })
59534             .call(tooltip()
59535                 .placement('bottom')
59536                 .html(true)
59537                 .title(function(mode) {
59538                     return uiTooltipHtml(mode.description, mode.key);
59539                 })
59540             );
59541
59542         context.map()
59543             .on('move.modes', lodash.debounce(update, 500));
59544
59545         context
59546             .on('enter.modes', update);
59547
59548         buttons
59549             .each(function(d) {
59550                 select(this)
59551                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
59552             });
59553
59554         buttons
59555             .append('span')
59556             .attr('class', 'label')
59557             .text(function(mode) { return mode.title; });
59558
59559         context
59560             .on('enter.editor', function(entered) {
59561                 selection$$1.selectAll('button.add-button')
59562                     .classed('active', function(mode) { return entered.button === mode.button; });
59563                 context.container()
59564                     .classed('mode-' + entered.id, true);
59565             });
59566
59567         context
59568             .on('exit.editor', function(exited) {
59569                 context.container()
59570                     .classed('mode-' + exited.id, false);
59571             });
59572
59573         var keybinding = d3keybinding('mode-buttons');
59574
59575         modes.forEach(function(m) {
59576             keybinding.on(m.key, function() {
59577                 if (editable()) context.enter(m);
59578             });
59579         });
59580
59581         select(document)
59582             .call(keybinding);
59583
59584
59585         function update() {
59586             selection$$1.selectAll('button.add-button')
59587                 .property('disabled', !editable());
59588         }
59589     };
59590 }
59591
59592 function uiRestore(context) {
59593
59594     return function(selection) {
59595         if (!context.history().lock() || !context.history().restorableChanges())
59596             return;
59597
59598         var modalSelection = uiModal(selection, true);
59599
59600         modalSelection.select('.modal')
59601             .attr('class', 'modal fillL col6');
59602
59603         var introModal = modalSelection.select('.content');
59604
59605         introModal
59606             .attr('class','cf');
59607
59608         introModal
59609             .append('div')
59610             .attr('class', 'modal-section')
59611             .append('h3')
59612             .text(t('restore.heading'));
59613
59614         introModal
59615             .append('div')
59616             .attr('class','modal-section')
59617             .append('p')
59618             .text(t('restore.description'));
59619
59620         var buttonWrap = introModal
59621             .append('div')
59622             .attr('class', 'modal-actions cf');
59623
59624         var restore = buttonWrap
59625             .append('button')
59626             .attr('class', 'restore col6')
59627             .text(t('restore.restore'))
59628             .on('click', function() {
59629                 context.history().restore();
59630                 modalSelection.remove();
59631             });
59632
59633         buttonWrap
59634             .append('button')
59635             .attr('class', 'reset col6')
59636             .text(t('restore.reset'))
59637             .on('click', function() {
59638                 context.history().clearSaved();
59639                 modalSelection.remove();
59640             });
59641
59642         restore.node().focus();
59643     };
59644 }
59645
59646 function uiSave(context) {
59647     var history = context.history(),
59648         key = uiCmd('⌘S');
59649
59650
59651     function saving() {
59652         return context.mode().id === 'save';
59653     }
59654
59655
59656     function save() {
59657         event.preventDefault();
59658         if (!context.inIntro() && !saving() && history.hasChanges()) {
59659             context.enter(modeSave$$1(context));
59660         }
59661     }
59662
59663
59664     function getBackground(numChanges) {
59665         var step;
59666         if (numChanges === 0) {
59667             return null;
59668         } else if (numChanges <= 50) {
59669             step = numChanges / 50;
59670             return rgb$1('#fff', '#ff8')(step);  // white -> yellow
59671         } else {
59672             step = Math.min((numChanges - 50) / 50, 1.0);
59673             return rgb$1('#ff8', '#f88')(step);  // yellow -> red
59674         }
59675     }
59676
59677
59678     return function(selection$$1) {
59679         var numChanges = 0;
59680
59681         function updateCount() {
59682             var _ = history.difference().summary().length;
59683             if (_ === numChanges) return;
59684             numChanges = _;
59685
59686             tooltipBehavior
59687                 .title(uiTooltipHtml(
59688                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key)
59689                 );
59690
59691             var background = getBackground(numChanges);
59692
59693             button
59694                 .classed('disabled', numChanges === 0)
59695                 .classed('has-count', numChanges > 0)
59696                 .style('background', background);
59697
59698             button.select('span.count')
59699                 .text(numChanges)
59700                 .style('background', background)
59701                 .style('border-color', background);
59702         }
59703
59704
59705         var tooltipBehavior = tooltip()
59706             .placement('bottom')
59707             .html(true)
59708             .title(uiTooltipHtml(t('save.no_changes'), key));
59709
59710         var button = selection$$1
59711             .append('button')
59712             .attr('class', 'save col12 disabled')
59713             .attr('tabindex', -1)
59714             .on('click', save)
59715             .call(tooltipBehavior);
59716
59717         button
59718             .call(svgIcon('#icon-save', 'pre-text'))
59719             .append('span')
59720             .attr('class', 'label')
59721             .text(t('save.title'));
59722
59723         button
59724             .append('span')
59725             .attr('class', 'count')
59726             .text('0');
59727
59728         updateCount();
59729
59730
59731         var keybinding = d3keybinding('save')
59732             .on(key, save, true);
59733
59734         select(document)
59735             .call(keybinding);
59736
59737         context.history()
59738             .on('change.save', updateCount);
59739
59740         context
59741             .on('enter.save', function() {
59742                 button.property('disabled', saving());
59743                 if (saving()) button.call(tooltipBehavior.hide);
59744             });
59745     };
59746 }
59747
59748 function uiScale(context) {
59749     var projection = context.projection,
59750         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
59751         maxLength = 180,
59752         tickHeight = 8;
59753
59754
59755     function scaleDefs(loc1, loc2) {
59756         var lat = (loc2[1] + loc1[1]) / 2,
59757             conversion = (isImperial ? 3.28084 : 1),
59758             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
59759             scale = { dist: 0, px: 0, text: '' },
59760             buckets, i, val, dLon;
59761
59762         if (isImperial) {
59763             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
59764         } else {
59765             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
59766         }
59767
59768         // determine a user-friendly endpoint for the scale
59769         for (i = 0; i < buckets.length; i++) {
59770             val = buckets[i];
59771             if (dist >= val) {
59772                 scale.dist = Math.floor(dist / val) * val;
59773                 break;
59774             } else {
59775                 scale.dist = +dist.toFixed(2);
59776             }
59777         }
59778
59779         dLon = geoMetersToLon(scale.dist / conversion, lat);
59780         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
59781
59782         if (isImperial) {
59783             if (scale.dist >= 5280) {
59784                 scale.dist /= 5280;
59785                 scale.text = String(scale.dist) + ' mi';
59786             } else {
59787                 scale.text = String(scale.dist) + ' ft';
59788             }
59789         } else {
59790             if (scale.dist >= 1000) {
59791                 scale.dist /= 1000;
59792                 scale.text = String(scale.dist) + ' km';
59793             } else {
59794                 scale.text = String(scale.dist) + ' m';
59795             }
59796         }
59797
59798         return scale;
59799     }
59800
59801
59802     function update(selection) {
59803         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
59804         var dims = context.map().dimensions(),
59805             loc1 = projection.invert([0, dims[1]]),
59806             loc2 = projection.invert([maxLength, dims[1]]),
59807             scale = scaleDefs(loc1, loc2);
59808
59809         selection.select('#scalepath')
59810             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
59811
59812         selection.select('#scaletext')
59813             .attr('x', scale.px + 8)
59814             .attr('y', tickHeight)
59815             .text(scale.text);
59816     }
59817
59818
59819     return function(selection) {
59820         function switchUnits() {
59821             isImperial = !isImperial;
59822             selection.call(update);
59823         }
59824
59825         var g = selection.append('svg')
59826             .attr('id', 'scale')
59827             .on('click', switchUnits)
59828             .append('g')
59829             .attr('transform', 'translate(10,11)');
59830
59831         g.append('path').attr('id', 'scalepath');
59832         g.append('text').attr('id', 'scaletext');
59833
59834         selection.call(update);
59835
59836         context.map().on('move.scale', function() {
59837             update(selection);
59838         });
59839     };
59840 }
59841
59842 var pair_1 = pair;
59843 function search(x, dims, r) {
59844   if (!dims) dims = 'NSEW';
59845   if (typeof x !== 'string') return { val: null, regex: r };
59846   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
59847   var m = r.exec(x);
59848   if (!m) return { val: null, regex: r };
59849   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
59850   else return {
59851     val: (((m[1]) ? parseFloat(m[1]) : 0) +
59852           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
59853           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
59854           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
59855     regex: r,
59856     raw: m[0],
59857     dim: m[4]
59858   };
59859 }
59860
59861 function pair(x, dims) {
59862   x = x.trim();
59863   var one = search(x, dims);
59864   if (one.val === null) return null;
59865   var two = search(x, dims, one.regex);
59866   if (two.val === null) return null;
59867   // null if one/two are not contiguous.
59868   if (one.raw + two.raw !== x) return null;
59869   if (one.dim) {
59870     return swapdim(one.val, two.val, one.dim);
59871   } else {
59872     return [one.val, two.val];
59873   }
59874 }
59875
59876 function swapdim(a, b, dim) {
59877   if (dim === 'N' || dim === 'S') return [a, b];
59878   if (dim === 'W' || dim === 'E') return [b, a];
59879 }
59880
59881 function uiFeatureList(context) {
59882     var geocodeResults;
59883
59884
59885     function featureList(selection$$1) {
59886         var header = selection$$1.append('div')
59887             .attr('class', 'header fillL cf');
59888
59889         header.append('h3')
59890             .text(t('inspector.feature_list'));
59891
59892         var searchWrap = selection$$1.append('div')
59893             .attr('class', 'search-header');
59894
59895         var search = searchWrap.append('input')
59896             .attr('placeholder', t('inspector.search'))
59897             .attr('type', 'search')
59898             .on('keypress', keypress)
59899             .on('input', inputevent);
59900
59901         searchWrap
59902             .call(svgIcon('#icon-search', 'pre-text'));
59903
59904         var listWrap = selection$$1.append('div')
59905             .attr('class', 'inspector-body');
59906
59907         var list = listWrap.append('div')
59908             .attr('class', 'feature-list cf');
59909
59910         context
59911             .on('exit.feature-list', clearSearch);
59912         context.map()
59913             .on('drawn.feature-list', mapDrawn);
59914
59915
59916         function keypress() {
59917             var q = search.property('value'),
59918                 items = list.selectAll('.feature-list-item');
59919             if (event.keyCode === 13 && q.length && items.size()) {
59920                 click(items.datum());
59921             }
59922         }
59923
59924
59925         function inputevent() {
59926             geocodeResults = undefined;
59927             drawList();
59928         }
59929
59930
59931         function clearSearch() {
59932             search.property('value', '');
59933             drawList();
59934         }
59935
59936
59937         function mapDrawn(e) {
59938             if (e.full) {
59939                 drawList();
59940             }
59941         }
59942
59943
59944         function features() {
59945             var entities = {},
59946                 result = [],
59947                 graph = context.graph(),
59948                 q = search.property('value').toLowerCase();
59949
59950             if (!q) return result;
59951
59952             var idMatch = q.match(/^([nwr])([0-9]+)$/);
59953
59954             if (idMatch) {
59955                 result.push({
59956                     id: idMatch[0],
59957                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
59958                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
59959                     name: idMatch[2]
59960                 });
59961             }
59962
59963             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
59964
59965             if (locationMatch) {
59966                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
59967                 result.push({
59968                     id: -1,
59969                     geometry: 'point',
59970                     type: t('inspector.location'),
59971                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
59972                     location: loc
59973                 });
59974             }
59975
59976             function addEntity(entity) {
59977                 if (entity.id in entities || result.length > 200)
59978                     return;
59979
59980                 entities[entity.id] = true;
59981
59982                 var name = utilDisplayName(entity) || '';
59983                 if (name.toLowerCase().indexOf(q) >= 0) {
59984                     var matched = context.presets().match(entity, graph),
59985                         type = (matched && matched.name()) || utilDisplayType(entity.id);
59986                     result.push({
59987                         id: entity.id,
59988                         entity: entity,
59989                         geometry: context.geometry(entity.id),
59990                         type: type,
59991                         name: name
59992                     });
59993                 }
59994
59995                 graph.parentRelations(entity).forEach(function(parent) {
59996                     addEntity(parent);
59997                 });
59998             }
59999
60000             var visible = context.surface().selectAll('.point, .line, .area').nodes();
60001             for (var i = 0; i < visible.length && result.length <= 200; i++) {
60002                 addEntity(visible[i].__data__);
60003             }
60004
60005             (geocodeResults || []).forEach(function(d) {
60006                 // https://github.com/openstreetmap/iD/issues/1890
60007                 if (d.osm_type && d.osm_id) {
60008                     result.push({
60009                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
60010                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
60011                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
60012                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
60013                         name: d.display_name,
60014                         extent: new geoExtent$$1(
60015                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
60016                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
60017                     });
60018                 }
60019             });
60020
60021             return result;
60022         }
60023
60024
60025         function drawList() {
60026             var value = search.property('value'),
60027                 results = features();
60028
60029             list.classed('filtered', value.length);
60030
60031             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
60032
60033             var resultsIndicator = list.selectAll('.no-results-item')
60034                 .data([0])
60035                 .enter().append('button')
60036                 .property('disabled', true)
60037                 .attr('class', 'no-results-item')
60038                 .call(svgIcon('#icon-alert', 'pre-text'));
60039
60040             resultsIndicator.append('span')
60041                 .attr('class', 'entity-name');
60042
60043             list.selectAll('.no-results-item .entity-name')
60044                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
60045
60046             list.selectAll('.geocode-item')
60047                 .data([0])
60048                 .enter().append('button')
60049                 .attr('class', 'geocode-item')
60050                 .on('click', geocoderSearch)
60051                 .append('div')
60052                 .attr('class', 'label')
60053                 .append('span')
60054                 .attr('class', 'entity-name')
60055                 .text(t('geocoder.search'));
60056
60057             list.selectAll('.no-results-item')
60058                 .style('display', (value.length && !results.length) ? 'block' : 'none');
60059
60060             list.selectAll('.geocode-item')
60061                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
60062
60063             list.selectAll('.feature-list-item')
60064                 .data([-1])
60065                 .remove();
60066
60067             var items = list.selectAll('.feature-list-item')
60068                 .data(results, function(d) { return d.id; });
60069
60070             var enter = items.enter()
60071                 .insert('button', '.geocode-item')
60072                 .attr('class', 'feature-list-item')
60073                 .on('mouseover', mouseover)
60074                 .on('mouseout', mouseout)
60075                 .on('click', click);
60076
60077             var label = enter
60078                 .append('div')
60079                 .attr('class', 'label');
60080
60081             label.each(function(d) {
60082                 select(this)
60083                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
60084             });
60085
60086             label.append('span')
60087                 .attr('class', 'entity-type')
60088                 .text(function(d) { return d.type; });
60089
60090             label.append('span')
60091                 .attr('class', 'entity-name')
60092                 .text(function(d) { return d.name; });
60093
60094             enter.style('opacity', 0)
60095                 .transition()
60096                 .style('opacity', 1);
60097
60098             items.order();
60099
60100             items.exit()
60101                 .remove();
60102         }
60103
60104
60105         function mouseover(d) {
60106             if (d.id === -1) return;
60107
60108             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
60109                 .classed('hover', true);
60110         }
60111
60112
60113         function mouseout() {
60114             context.surface().selectAll('.hover')
60115                 .classed('hover', false);
60116         }
60117
60118
60119         function click(d) {
60120             event.preventDefault();
60121             if (d.location) {
60122                 context.map().centerZoom([d.location[1], d.location[0]], 20);
60123             }
60124             else if (d.entity) {
60125                 if (d.entity.type === 'node') {
60126                     context.map().center(d.entity.loc);
60127                 } else if (d.entity.type === 'way') {
60128                     var center = context.projection(context.map().center()),
60129                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
60130                     context.map().center(edge.loc);
60131                 }
60132                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
60133             } else {
60134                 context.zoomToEntity(d.id);
60135             }
60136         }
60137
60138
60139         function geocoderSearch() {
60140             services.geocoder.search(search.property('value'), function (err, resp) {
60141                 geocodeResults = resp || [];
60142                 drawList();
60143             });
60144         }
60145     }
60146
60147
60148     return featureList;
60149 }
60150
60151 function uiPresetIcon() {
60152     var preset, geometry;
60153
60154
60155     function presetIcon(selection$$1) {
60156         selection$$1.each(render);
60157     }
60158
60159
60160     function render() {
60161         var selection$$1 = select(this),
60162             p = preset.apply(this, arguments),
60163             geom = geometry.apply(this, arguments),
60164             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
60165             isMaki = dataFeatureIcons.indexOf(picon) !== -1;
60166
60167         function tag_classes(p) {
60168             var s = '';
60169             for (var i in p.tags) {
60170                 s += ' tag-' + i;
60171                 if (p.tags[i] !== '*') {
60172                     s += ' tag-' + i + '-' + p.tags[i];
60173                 }
60174             }
60175             return s;
60176         }
60177
60178         var fill = selection$$1.selectAll('.preset-icon-fill')
60179             .data([0]);
60180
60181         fill = fill.enter()
60182             .append('div')
60183             .merge(fill);
60184
60185         fill
60186             .attr('class', function() {
60187                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
60188             });
60189
60190         var frame = selection$$1.selectAll('.preset-icon-frame')
60191             .data([0]);
60192
60193         frame = frame.enter()
60194             .append('div')
60195             .call(svgIcon('#preset-icon-frame'))
60196             .merge(frame);
60197
60198         frame
60199             .attr('class', function() {
60200                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
60201             });
60202
60203
60204         var icon = selection$$1.selectAll('.preset-icon')
60205             .data([0]);
60206
60207         icon = icon.enter()
60208             .append('div')
60209             .attr('class', 'preset-icon')
60210             .call(svgIcon(''))
60211             .merge(icon);
60212
60213         icon
60214             .attr('class', 'preset-icon preset-icon-' +
60215                 (isMaki ? (geom === 'area' ? '24' : '28') : (geom === 'area' ? '44' : '60'))
60216             );
60217
60218         icon.selectAll('svg')
60219             .attr('class', function() {
60220                 return 'icon ' + picon + (isMaki ? '' : tag_classes(p));
60221             });
60222
60223         icon.selectAll('use')
60224             .attr('href', '#' + picon + (isMaki ? '-15' : ''));
60225     }
60226
60227
60228     presetIcon.preset = function(_) {
60229         if (!arguments.length) return preset;
60230         preset = utilFunctor(_);
60231         return presetIcon;
60232     };
60233
60234
60235     presetIcon.geometry = function(_) {
60236         if (!arguments.length) return geometry;
60237         geometry = utilFunctor(_);
60238         return presetIcon;
60239     };
60240
60241     return presetIcon;
60242 }
60243
60244 function d3combobox() {
60245     var event$$1 = dispatch('accept'),
60246         data = [],
60247         suggestions = [],
60248         minItems = 2,
60249         caseSensitive = false;
60250
60251     var fetcher = function(val, cb) {
60252         cb(data.filter(function(d) {
60253             return d.value
60254                 .toString()
60255                 .toLowerCase()
60256                 .indexOf(val.toLowerCase()) !== -1;
60257         }));
60258     };
60259
60260     var combobox = function(input, attachTo) {
60261         var idx = -1,
60262             container = select(document.body)
60263                 .selectAll('div.combobox')
60264                 .filter(function(d) { return d === input.node(); }),
60265             shown = !container.empty();
60266
60267         input
60268             .classed('combobox-input', true)
60269             .on('focus.typeahead', focus)
60270             .on('blur.typeahead', blur)
60271             .on('keydown.typeahead', keydown)
60272             .on('keyup.typeahead', keyup)
60273             .on('input.typeahead', change)
60274             .each(function() {
60275                 var parent = this.parentNode,
60276                     sibling = this.nextSibling;
60277
60278                 var caret = select(parent).selectAll('.combobox-caret')
60279                     .filter(function(d) { return d === input.node(); })
60280                     .data([input.node()]);
60281
60282                 caret = caret.enter()
60283                   .insert('div', function() { return sibling; })
60284                     .attr('class', 'combobox-caret')
60285                   .merge(caret);
60286
60287                 caret
60288                     .on('mousedown', function () {
60289                         // prevent the form element from blurring. it blurs
60290                         // on mousedown
60291                         event.stopPropagation();
60292                         event.preventDefault();
60293                         if (!shown) {
60294                             input.node().focus();
60295                             fetch('', render);
60296                         } else {
60297                             hide();
60298                         }
60299                     });
60300             });
60301
60302         function focus() {
60303             fetch(value(), render);
60304         }
60305
60306         function blur() {
60307             window.setTimeout(hide, 150);
60308         }
60309
60310         function show() {
60311             if (!shown) {
60312                 container = select(document.body)
60313                     .insert('div', ':first-child')
60314                     .datum(input.node())
60315                     .attr('class', 'combobox')
60316                     .style('position', 'absolute')
60317                     .style('display', 'block')
60318                     .style('left', '0px')
60319                     .on('mousedown', function () {
60320                         // prevent moving focus out of the text field
60321                         event.preventDefault();
60322                     });
60323
60324                 select(document.body)
60325                     .on('scroll.combobox', render, true);
60326
60327                 shown = true;
60328             }
60329         }
60330
60331         function hide() {
60332             if (shown) {
60333                 idx = -1;
60334                 container.remove();
60335
60336                 select(document.body)
60337                     .on('scroll.combobox', null);
60338
60339                 shown = false;
60340             }
60341         }
60342
60343         function keydown() {
60344            switch (event.keyCode) {
60345                // backspace, delete
60346                case 8:
60347                case 46:
60348                    input.on('input.typeahead', function() {
60349                        idx = -1;
60350                        render();
60351                        var start = input.property('selectionStart');
60352                        input.node().setSelectionRange(start, start);
60353                        input.on('input.typeahead', change);
60354                    });
60355                    break;
60356                // tab
60357                case 9:
60358                    container.selectAll('a.selected').each(function (d) {
60359                        event$$1.call('accept', this, d);
60360                    });
60361                    hide();
60362                    break;
60363                // return
60364                case 13:
60365                    event.preventDefault();
60366                    break;
60367                // up arrow
60368                case 38:
60369                    nav(-1);
60370                    event.preventDefault();
60371                    break;
60372                // down arrow
60373                case 40:
60374                    nav(+1);
60375                    event.preventDefault();
60376                    break;
60377            }
60378            event.stopPropagation();
60379         }
60380
60381         function keyup() {
60382             switch (event.keyCode) {
60383                 // escape
60384                 case 27:
60385                     hide();
60386                     break;
60387                 // return
60388                 case 13:
60389                     container.selectAll('a.selected').each(function (d) {
60390                        event$$1.call('accept', this, d);
60391                     });
60392                     hide();
60393                     break;
60394             }
60395         }
60396
60397         function change() {
60398             fetch(value(), function() {
60399                 if (input.property('selectionEnd') === input.property('value').length) {
60400                     autocomplete();
60401                 }
60402                 render();
60403             });
60404         }
60405
60406         function nav(dir) {
60407             if (!suggestions.length) return;
60408             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
60409             input.property('value', suggestions[idx].value);
60410             render();
60411             ensureVisible();
60412         }
60413
60414         function value() {
60415             var value = input.property('value'),
60416                 start = input.property('selectionStart'),
60417                 end = input.property('selectionEnd');
60418
60419             if (start && end) {
60420                 value = value.substring(0, start);
60421             }
60422
60423             return value;
60424         }
60425
60426         function fetch(v, cb) {
60427             fetcher.call(input, v, function(_) {
60428                 suggestions = _;
60429                 cb();
60430             });
60431         }
60432
60433         function autocomplete() {
60434             var v = caseSensitive ? value() : value().toLowerCase();
60435             idx = -1;
60436             if (!v) return;
60437
60438             for (var i = 0; i < suggestions.length; i++) {
60439                 var suggestion = suggestions[i].value,
60440                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
60441
60442                 if (compare.indexOf(v) === 0) {
60443                     idx = i;
60444                     input.property('value', suggestion);
60445                     input.node().setSelectionRange(v.length, suggestion.length);
60446                     return;
60447                 }
60448             }
60449         }
60450
60451         function render() {
60452             if (suggestions.length >= minItems && document.activeElement === input.node()) {
60453                 show();
60454             } else {
60455                 hide();
60456                 return;
60457             }
60458
60459             var options = container
60460                 .selectAll('a.combobox-option')
60461                 .data(suggestions, function(d) { return d.value; });
60462
60463             options.exit()
60464                 .remove();
60465
60466             options.enter()
60467                 .append('a')
60468                 .attr('class', 'combobox-option')
60469                 .text(function(d) { return d.value; })
60470                 .merge(options)
60471                 .attr('title', function(d) { return d.title; })
60472                 .classed('selected', function(d, i) { return i === idx; })
60473                 .on('mouseover', select$$1)
60474                 .on('click', accept)
60475                 .order();
60476
60477
60478             var node = attachTo ? attachTo.node() : input.node(),
60479                 rect = node.getBoundingClientRect();
60480
60481             container
60482                 .style('left', rect.left + 'px')
60483                 .style('width', rect.width + 'px')
60484                 .style('top', rect.height + rect.top + 'px');
60485         }
60486
60487         function select$$1(d, i) {
60488             idx = i;
60489             render();
60490         }
60491
60492         function ensureVisible() {
60493             var node = container.selectAll('a.selected').node();
60494             if (node) node.scrollIntoView();
60495         }
60496
60497         function accept(d) {
60498             if (!shown) return;
60499             input
60500                 .property('value', d.value)
60501                 .dispatch('change');
60502             event$$1.call('accept', this, d);
60503             hide();
60504         }
60505     };
60506
60507     combobox.fetcher = function(_) {
60508         if (!arguments.length) return fetcher;
60509         fetcher = _;
60510         return combobox;
60511     };
60512
60513     combobox.data = function(_) {
60514         if (!arguments.length) return data;
60515         data = _;
60516         return combobox;
60517     };
60518
60519     combobox.minItems = function(_) {
60520         if (!arguments.length) return minItems;
60521         minItems = _;
60522         return combobox;
60523     };
60524
60525     combobox.caseSensitive = function(_) {
60526         if (!arguments.length) return caseSensitive;
60527         caseSensitive = _;
60528         return combobox;
60529     };
60530
60531     return utilRebind(combobox, event$$1, 'on');
60532 }
60533
60534
60535 d3combobox.off = function(input) {
60536     input
60537         .on('focus.typeahead', null)
60538         .on('blur.typeahead', null)
60539         .on('keydown.typeahead', null)
60540         .on('keyup.typeahead', null)
60541         .on('input.typeahead', null)
60542         .each(function() {
60543             select(this.parentNode).selectAll('.combobox-caret')
60544                 .filter(function(d) { return d === input.node(); })
60545                 .on('mousedown', null);
60546         });
60547
60548     select(document.body)
60549         .on('scroll.combobox', null);
60550 };
60551
60552 function uiDisclosure() {
60553     var dispatch$$1 = dispatch('toggled'),
60554         title,
60555         expanded = false,
60556         content = function () {};
60557
60558
60559     var disclosure = function(selection$$1) {
60560         var hideToggle = selection$$1.selectAll('.hide-toggle')
60561             .data([0]);
60562
60563         hideToggle = hideToggle.enter()
60564             .append('a')
60565             .attr('href', '#')
60566             .attr('class', 'hide-toggle')
60567             .merge(hideToggle);
60568
60569         hideToggle
60570             .text(title)
60571             .on('click', toggle)
60572             .classed('expanded', expanded);
60573
60574
60575         var wrap = selection$$1.selectAll('div')
60576             .data([0]);
60577
60578         wrap = wrap.enter()
60579             .append('div')
60580             .merge(wrap);
60581
60582         wrap
60583             .classed('hide', !expanded)
60584             .call(content);
60585
60586
60587         function toggle() {
60588             expanded = !expanded;
60589             hideToggle.classed('expanded', expanded);
60590             wrap.call(uiToggle(expanded));
60591             dispatch$$1.call('toggled', this, expanded);
60592         }
60593     };
60594
60595
60596     disclosure.title = function(_) {
60597         if (!arguments.length) return title;
60598         title = _;
60599         return disclosure;
60600     };
60601
60602
60603     disclosure.expanded = function(_) {
60604         if (!arguments.length) return expanded;
60605         expanded = _;
60606         return disclosure;
60607     };
60608
60609
60610     disclosure.content = function(_) {
60611         if (!arguments.length) return content;
60612         content = _;
60613         return disclosure;
60614     };
60615
60616
60617     return utilRebind(disclosure, dispatch$$1, 'on');
60618 }
60619
60620 function uiRawMemberEditor(context) {
60621     var id,
60622         taginfo = services.taginfo;
60623
60624
60625     function selectMember(d) {
60626         event.preventDefault();
60627         context.enter(modeSelect(context, [d.id]).suppressMenu(true));
60628     }
60629
60630
60631     function changeRole(d) {
60632         var role = select(this).property('value');
60633         var member = { id: d.id, type: d.type, role: role };
60634         context.perform(
60635             actionChangeMember(d.relation.id, member, d.index),
60636             t('operations.change_role.annotation')
60637         );
60638     }
60639
60640
60641     function deleteMember(d) {
60642         context.perform(
60643             actionDeleteMember(d.relation.id, d.index),
60644             t('operations.delete_member.annotation')
60645         );
60646
60647         if (!context.hasEntity(d.relation.id)) {
60648             context.enter(modeBrowse(context));
60649         }
60650     }
60651
60652
60653     function rawMemberEditor(selection$$1) {
60654         var entity = context.entity(id),
60655             memberships = [];
60656
60657         entity.members.forEach(function(member, index) {
60658             memberships.push({
60659                 index: index,
60660                 id: member.id,
60661                 type: member.type,
60662                 role: member.role,
60663                 relation: entity,
60664                 member: context.hasEntity(member.id)
60665             });
60666         });
60667
60668         selection$$1.call(uiDisclosure()
60669             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
60670             .expanded(true)
60671             .on('toggled', toggled)
60672             .content(content)
60673         );
60674
60675
60676         function toggled(expanded) {
60677             if (expanded) {
60678                 selection$$1.node().parentNode.scrollTop += 200;
60679             }
60680         }
60681
60682
60683         function content(wrap) {
60684             var list = wrap.selectAll('.member-list')
60685                 .data([0]);
60686
60687             list = list.enter()
60688                 .append('ul')
60689                 .attr('class', 'member-list')
60690                 .merge(list);
60691
60692
60693             var items = list.selectAll('li')
60694                 .data(memberships, function(d) {
60695                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
60696                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
60697                 });
60698
60699             items.exit()
60700                 .each(unbind)
60701                 .remove();
60702
60703             var enter = items.enter()
60704                 .append('li')
60705                 .attr('class', 'member-row form-field')
60706                 .classed('member-incomplete', function(d) { return !d.member; });
60707
60708             enter
60709                 .each(function(d) {
60710                     if (d.member) {
60711                         var label = select(this).append('label')
60712                             .attr('class', 'form-label')
60713                             .append('a')
60714                             .attr('href', '#')
60715                             .on('click', selectMember);
60716
60717                         label.append('span')
60718                             .attr('class', 'member-entity-type')
60719                             .text(function(d) {
60720                                 var matched = context.presets().match(d.member, context.graph());
60721                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
60722                             });
60723
60724                         label.append('span')
60725                             .attr('class', 'member-entity-name')
60726                             .text(function(d) { return utilDisplayName(d.member); });
60727
60728                     } else {
60729                         select(this).append('label')
60730                             .attr('class', 'form-label')
60731                             .text(t('inspector.incomplete', { id: d.id }));
60732                     }
60733                 });
60734
60735             enter
60736                 .append('input')
60737                 .attr('class', 'member-role')
60738                 .property('type', 'text')
60739                 .attr('maxlength', 255)
60740                 .attr('placeholder', t('inspector.role'))
60741                 .property('value', function(d) { return d.role; })
60742                 .on('change', changeRole);
60743
60744             enter
60745                 .append('button')
60746                 .attr('tabindex', -1)
60747                 .attr('class', 'remove button-input-action member-delete minor')
60748                 .on('click', deleteMember)
60749                 .call(svgIcon('#operation-delete'));
60750
60751             if (taginfo) {
60752                 enter.each(bindTypeahead);
60753             }
60754
60755
60756             function bindTypeahead(d) {
60757                 var row = select(this),
60758                     role = row.selectAll('input.member-role');
60759
60760                 function sort(value, data) {
60761                     var sameletter = [],
60762                         other = [];
60763                     for (var i = 0; i < data.length; i++) {
60764                         if (data[i].value.substring(0, value.length) === value) {
60765                             sameletter.push(data[i]);
60766                         } else {
60767                             other.push(data[i]);
60768                         }
60769                     }
60770                     return sameletter.concat(other);
60771                 }
60772
60773                 role.call(d3combobox()
60774                     .fetcher(function(role, callback) {
60775                         var rtype = entity.tags.type;
60776                         taginfo.roles({
60777                             debounce: true,
60778                             rtype: rtype || '',
60779                             geometry: context.geometry(d.member.id),
60780                             query: role
60781                         }, function(err, data) {
60782                             if (!err) callback(sort(role, data));
60783                         });
60784                     }));
60785             }
60786
60787
60788             function unbind() {
60789                 var row = select(this);
60790
60791                 row.selectAll('input.member-role')
60792                     .call(d3combobox.off);
60793             }
60794         }
60795     }
60796
60797
60798     rawMemberEditor.entityID = function(_) {
60799         if (!arguments.length) return id;
60800         id = _;
60801         return rawMemberEditor;
60802     };
60803
60804
60805     return rawMemberEditor;
60806 }
60807
60808 function uiRawMembershipEditor(context) {
60809     var taginfo = services.taginfo,
60810         id, showBlank;
60811
60812
60813     function selectRelation(d) {
60814         event.preventDefault();
60815         context.enter(modeSelect(context, [d.relation.id]).suppressMenu(true));
60816     }
60817
60818
60819     function changeRole(d) {
60820         var role = select(this).property('value');
60821         context.perform(
60822             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
60823             t('operations.change_role.annotation')
60824         );
60825     }
60826
60827
60828     function addMembership(d, role) {
60829         showBlank = false;
60830
60831         if (d.relation) {
60832             context.perform(
60833                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
60834                 t('operations.add_member.annotation')
60835             );
60836
60837         } else {
60838             var relation = osmRelation();
60839             context.perform(
60840                 actionAddEntity(relation),
60841                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
60842                 t('operations.add.annotation.relation')
60843             );
60844
60845             context.enter(modeSelect(context, [relation.id]).suppressMenu(true));
60846         }
60847     }
60848
60849
60850     function deleteMembership(d) {
60851         context.perform(
60852             actionDeleteMember(d.relation.id, d.index),
60853             t('operations.delete_member.annotation')
60854         );
60855     }
60856
60857
60858     function relations(q) {
60859         var newRelation = {
60860                 relation: null,
60861                 value: t('inspector.new_relation')
60862             },
60863             result = [],
60864             graph = context.graph();
60865
60866         context.intersects(context.extent()).forEach(function(entity) {
60867             if (entity.type !== 'relation' || entity.id === id)
60868                 return;
60869
60870             var matched = context.presets().match(entity, graph),
60871                 presetName = (matched && matched.name()) || t('inspector.relation'),
60872                 entityName = utilDisplayName(entity) || '';
60873
60874             var value = presetName + ' ' + entityName;
60875             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
60876                 return;
60877
60878             result.push({
60879                 relation: entity,
60880                 value: value
60881             });
60882         });
60883
60884         result.sort(function(a, b) {
60885             return osmRelation.creationOrder(a.relation, b.relation);
60886         });
60887
60888         // Dedupe identical names by appending relation id - see #2891
60889         var dupeGroups = lodash(result)
60890             .groupBy('value')
60891             .filter(function(v) { return v.length > 1; })
60892             .value();
60893
60894         dupeGroups.forEach(function(group) {
60895             group.forEach(function(obj) {
60896                 obj.value += ' ' + obj.relation.id;
60897             });
60898         });
60899
60900         result.unshift(newRelation);
60901         return result;
60902     }
60903
60904
60905     function rawMembershipEditor(selection$$1) {
60906         var entity = context.entity(id),
60907             memberships = [];
60908
60909         context.graph().parentRelations(entity).forEach(function(relation) {
60910             relation.members.forEach(function(member, index) {
60911                 if (member.id === entity.id) {
60912                     memberships.push({ relation: relation, member: member, index: index });
60913                 }
60914             });
60915         });
60916
60917         selection$$1.call(uiDisclosure()
60918             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
60919             .expanded(true)
60920             .on('toggled', toggled)
60921             .content(content)
60922         );
60923
60924
60925         function toggled(expanded) {
60926             if (expanded) {
60927                 selection$$1.node().parentNode.scrollTop += 200;
60928             }
60929         }
60930
60931
60932         function content(wrap) {
60933             var list = wrap.selectAll('.member-list')
60934                 .data([0]);
60935
60936             list = list.enter()
60937                 .append('ul')
60938                 .attr('class', 'member-list')
60939                 .merge(list);
60940
60941
60942             var items = list.selectAll('li.member-row-normal')
60943                 .data(memberships, function(d) {
60944                     return osmEntity$$1.key(d.relation) + ',' + d.index;
60945                 });
60946
60947             items.exit()
60948                 .each(unbind)
60949                 .remove();
60950
60951             var enter = items.enter()
60952                 .append('li')
60953                 .attr('class', 'member-row member-row-normal form-field');
60954
60955             var label = enter
60956                 .append('label')
60957                 .attr('class', 'form-label')
60958                 .append('a')
60959                 .attr('href', '#')
60960                 .on('click', selectRelation);
60961
60962             label
60963                 .append('span')
60964                 .attr('class', 'member-entity-type')
60965                 .text(function(d) {
60966                     var matched = context.presets().match(d.relation, context.graph());
60967                     return (matched && matched.name()) || t('inspector.relation');
60968                 });
60969
60970             label
60971                 .append('span')
60972                 .attr('class', 'member-entity-name')
60973                 .text(function(d) { return utilDisplayName(d.relation); });
60974
60975             enter
60976                 .append('input')
60977                 .attr('class', 'member-role')
60978                 .property('type', 'text')
60979                 .attr('maxlength', 255)
60980                 .attr('placeholder', t('inspector.role'))
60981                 .property('value', function(d) { return d.member.role; })
60982                 .on('change', changeRole);
60983
60984             enter
60985                 .append('button')
60986                 .attr('tabindex', -1)
60987                 .attr('class', 'remove button-input-action member-delete minor')
60988                 .on('click', deleteMembership)
60989                 .call(svgIcon('#operation-delete'));
60990
60991             if (taginfo) {
60992                 enter.each(bindTypeahead);
60993             }
60994
60995
60996             var newrow = list.selectAll('.member-row-new')
60997                 .data(showBlank ? [0] : []);
60998
60999             newrow.exit()
61000                 .remove();
61001
61002             enter = newrow.enter()
61003                 .append('li')
61004                 .attr('class', 'member-row member-row-new form-field');
61005
61006             enter
61007                 .append('input')
61008                 .attr('type', 'text')
61009                 .attr('class', 'member-entity-input');
61010
61011             enter
61012                 .append('input')
61013                 .attr('class', 'member-role')
61014                 .property('type', 'text')
61015                 .attr('maxlength', 255)
61016                 .attr('placeholder', t('inspector.role'))
61017                 .on('change', changeRole);
61018
61019             enter
61020                 .append('button')
61021                 .attr('tabindex', -1)
61022                 .attr('class', 'remove button-input-action member-delete minor')
61023                 .on('click', deleteMembership)
61024                 .call(svgIcon('#operation-delete'));
61025
61026             newrow = newrow
61027                 .merge(enter);
61028
61029             newrow.selectAll('.member-entity-input')
61030                 .call(d3combobox()
61031                     .minItems(1)
61032                     .fetcher(function(value, callback) { callback(relations(value)); })
61033                     .on('accept', onAccept)
61034                 );
61035
61036
61037             var addrel = wrap.selectAll('.add-relation')
61038                 .data([0]);
61039
61040             addrel = addrel.enter()
61041                 .append('button')
61042                 .attr('class', 'add-relation')
61043                 .merge(addrel);
61044
61045             addrel
61046                 .call(svgIcon('#icon-plus', 'light'))
61047                 .on('click', function() {
61048                     showBlank = true;
61049                     content(wrap);
61050                     list.selectAll('.member-entity-input').node().focus();
61051                 });
61052
61053
61054             function onAccept(d) {
61055                 var role = list.selectAll('.member-row-new .member-role').property('value');
61056                 addMembership(d, role);
61057             }
61058
61059
61060             function bindTypeahead(d) {
61061                 var row = select(this),
61062                     role = row.selectAll('input.member-role');
61063
61064                 function sort(value, data) {
61065                     var sameletter = [],
61066                         other = [];
61067                     for (var i = 0; i < data.length; i++) {
61068                         if (data[i].value.substring(0, value.length) === value) {
61069                             sameletter.push(data[i]);
61070                         } else {
61071                             other.push(data[i]);
61072                         }
61073                     }
61074                     return sameletter.concat(other);
61075                 }
61076
61077                 role.call(d3combobox()
61078                     .fetcher(function(role, callback) {
61079                         var rtype = d.relation.tags.type;
61080                         taginfo.roles({
61081                             debounce: true,
61082                             rtype: rtype || '',
61083                             geometry: context.geometry(id),
61084                             query: role
61085                         }, function(err, data) {
61086                             if (!err) callback(sort(role, data));
61087                         });
61088                     }));
61089             }
61090
61091
61092             function unbind() {
61093                 var row = select(this);
61094
61095                 row.selectAll('input.member-role')
61096                     .call(d3combobox.off);
61097             }
61098         }
61099     }
61100
61101
61102     rawMembershipEditor.entityID = function(_) {
61103         if (!arguments.length) return id;
61104         id = _;
61105         return rawMembershipEditor;
61106     };
61107
61108
61109     return rawMembershipEditor;
61110 }
61111
61112 function uiTagReference(tag) {
61113     var taginfo = services.taginfo,
61114         tagReference = {},
61115         button,
61116         body,
61117         loaded,
61118         showing;
61119
61120
61121     function findLocal(data) {
61122         var locale = utilDetect().locale.toLowerCase(),
61123             localized;
61124
61125         if (locale !== 'pt-br') {  // see #3776, prefer 'pt' over 'pt-br'
61126             localized = lodash.find(data, function(d) {
61127                 return d.lang.toLowerCase() === locale;
61128             });
61129             if (localized) return localized;
61130         }
61131
61132         // try the non-regional version of a language, like
61133         // 'en' if the language is 'en-US'
61134         if (locale.indexOf('-') !== -1) {
61135             var first = locale.split('-')[0];
61136             localized = lodash.find(data, function(d) {
61137                 return d.lang.toLowerCase() === first;
61138             });
61139             if (localized) return localized;
61140         }
61141
61142         // finally fall back to english
61143         return lodash.find(data, function(d) {
61144             return d.lang.toLowerCase() === 'en';
61145         });
61146     }
61147
61148
61149     function load(param) {
61150         if (!taginfo) return;
61151
61152         button.classed('tag-reference-loading', true);
61153
61154         taginfo.docs(param, function show(err, data) {
61155             var docs;
61156             if (!err && data) {
61157                 docs = findLocal(data);
61158             }
61159
61160             body.html('');
61161
61162
61163             if (!docs || !docs.title) {
61164                 if (param.hasOwnProperty('value')) {
61165                     load(lodash.omit(param, 'value'));   // retry with key only
61166                 } else {
61167                     body.append('p').text(t('inspector.no_documentation_key'));
61168                     done();
61169                 }
61170                 return;
61171             }
61172
61173
61174             if (docs.image && docs.image.thumb_url_prefix) {
61175                 body
61176                     .append('img')
61177                     .attr('class', 'wiki-image')
61178                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
61179                     .on('load', function() { done(); })
61180                     .on('error', function() { select(this).remove(); done(); });
61181             } else {
61182                 done();
61183             }
61184
61185             body
61186                 .append('p')
61187                 .text(docs.description || t('inspector.documentation_redirect'));
61188
61189             body
61190                 .append('a')
61191                 .attr('target', '_blank')
61192                 .attr('tabindex', -1)
61193                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
61194                 .call(svgIcon('#icon-out-link', 'inline'))
61195                 .append('span')
61196                 .text(t('inspector.reference'));
61197         });
61198     }
61199
61200
61201     function done() {
61202         loaded = true;
61203
61204         button.classed('tag-reference-loading', false);
61205
61206         body.transition()
61207             .duration(200)
61208             .style('max-height', '200px')
61209             .style('opacity', '1');
61210
61211         showing = true;
61212     }
61213
61214
61215     function hide(selection$$1) {
61216         selection$$1 = selection$$1 || body.transition().duration(200);
61217
61218         selection$$1
61219             .style('max-height', '0px')
61220             .style('opacity', '0');
61221
61222         showing = false;
61223     }
61224
61225
61226     tagReference.button = function(selection$$1) {
61227         button = selection$$1.selectAll('.tag-reference-button')
61228             .data([0]);
61229
61230         button = button.enter()
61231             .append('button')
61232             .attr('class', 'tag-reference-button')
61233             .attr('tabindex', -1)
61234             .call(svgIcon('#icon-inspect'))
61235             .merge(button);
61236
61237         button
61238             .on('click', function () {
61239                 event.stopPropagation();
61240                 event.preventDefault();
61241                 if (showing) {
61242                     hide();
61243                 } else if (loaded) {
61244                     done();
61245                 } else {
61246                     load(tag);
61247                 }
61248             });
61249     };
61250
61251
61252     tagReference.body = function(selection$$1) {
61253         body = selection$$1.selectAll('.tag-reference-body')
61254             .data([0]);
61255
61256         body = body.enter()
61257             .append('div')
61258             .attr('class', 'tag-reference-body cf')
61259             .style('max-height', '0')
61260             .style('opacity', '0')
61261             .merge(body);
61262
61263         if (showing === false) {
61264             hide(body);
61265         }
61266     };
61267
61268
61269     tagReference.showing = function(_) {
61270         if (!arguments.length) return showing;
61271         showing = _;
61272         return tagReference;
61273     };
61274
61275
61276     return tagReference;
61277 }
61278
61279 function uiRawTagEditor(context) {
61280     var taginfo = services.taginfo,
61281         dispatch$$1 = dispatch('change'),
61282         showBlank = false,
61283         state,
61284         preset,
61285         tags,
61286         id;
61287
61288
61289     function rawTagEditor(selection$$1) {
61290         var count = Object.keys(tags).filter(function(d) { return d; }).length;
61291
61292         selection$$1.call(uiDisclosure()
61293             .title(t('inspector.all_tags') + ' (' + count + ')')
61294             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
61295             .on('toggled', toggled)
61296             .content(content));
61297
61298         function toggled(expanded) {
61299             context.storage('raw_tag_editor.expanded', expanded);
61300             if (expanded) {
61301                 selection$$1.node().parentNode.scrollTop += 200;
61302             }
61303         }
61304     }
61305
61306
61307     function content(wrap) {
61308         var entries$$1 = entries(tags);
61309
61310         if (!entries$$1.length || showBlank) {
61311             showBlank = false;
61312             entries$$1.push({key: '', value: ''});
61313         }
61314
61315         var list = wrap.selectAll('.tag-list')
61316             .data([0]);
61317
61318         list = list.enter()
61319             .append('ul')
61320             .attr('class', 'tag-list')
61321             .merge(list);
61322
61323         var newTag = wrap.selectAll('.add-tag')
61324             .data([0]);
61325
61326         newTag.enter()
61327             .append('button')
61328             .attr('class', 'add-tag')
61329             .on('click', addTag)
61330             .call(svgIcon('#icon-plus', 'light'));
61331
61332
61333         var items = list.selectAll('.tag-row')
61334             .data(entries$$1, function(d) { return d.key; });
61335
61336         items.exit()
61337             .each(unbind)
61338             .remove();
61339
61340         // Enter
61341
61342         var enter = items.enter()
61343             .append('li')
61344             .attr('class', 'tag-row cf');
61345
61346         enter
61347             .append('div')
61348             .attr('class', 'key-wrap')
61349             .append('input')
61350             .property('type', 'text')
61351             .attr('class', 'key')
61352             .attr('maxlength', 255)
61353             .on('blur', keyChange)
61354             .on('change', keyChange);
61355
61356         enter
61357             .append('div')
61358             .attr('class', 'input-wrap-position')
61359             .append('input')
61360             .property('type', 'text')
61361             .attr('class', 'value')
61362             .attr('maxlength', 255)
61363             .on('blur', valueChange)
61364             .on('change', valueChange)
61365             .on('keydown.push-more', pushMore);
61366
61367         enter
61368             .append('button')
61369             .attr('tabindex', -1)
61370             .attr('class', 'remove minor')
61371             .call(svgIcon('#operation-delete'));
61372
61373
61374         // Update
61375
61376         items = items
61377             .merge(enter)
61378             .sort(function(a, b) {
61379                 return (a.key === '') ? 1
61380                     : (b.key === '') ? -1
61381                     : ascending(a.key, b.key);
61382             });
61383
61384         items
61385             .each(function(tag) {
61386                 var row = select(this),
61387                     key = row.select('input.key'),      // propagate bound data to child
61388                     value = row.select('input.value');  // propagate bound data to child
61389
61390                 if (taginfo) {
61391                     bindTypeahead(key, value);
61392                 }
61393
61394                 var isRelation = (context.entity(id).type === 'relation'),
61395                     reference;
61396
61397                 if (isRelation && tag.key === 'type') {
61398                     reference = uiTagReference({ rtype: tag.value }, context);
61399                 } else {
61400                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
61401                 }
61402
61403                 if (state === 'hover') {
61404                     reference.showing(false);
61405                 }
61406
61407                 row
61408                     .call(reference.button)
61409                     .call(reference.body);
61410             });
61411
61412         items.selectAll('input.key')
61413             .attr('title', function(d) { return d.key; })
61414             .call(utilGetSetValue, function(d) { return d.key; });
61415
61416         items.selectAll('input.value')
61417             .attr('title', function(d) { return d.value; })
61418             .call(utilGetSetValue, function(d) { return d.value; });
61419
61420         items.selectAll('button.remove')
61421             .on('click', removeTag);
61422
61423
61424         function pushMore() {
61425             if (event.keyCode === 9 && !event.shiftKey &&
61426                 list.selectAll('li:last-child input.value').node() === this) {
61427                 addTag();
61428             }
61429         }
61430
61431
61432         function bindTypeahead(key, value) {
61433
61434             function sort(value, data) {
61435                 var sameletter = [],
61436                     other = [];
61437                 for (var i = 0; i < data.length; i++) {
61438                     if (data[i].value.substring(0, value.length) === value) {
61439                         sameletter.push(data[i]);
61440                     } else {
61441                         other.push(data[i]);
61442                     }
61443                 }
61444                 return sameletter.concat(other);
61445             }
61446
61447             key.call(d3combobox()
61448                 .fetcher(function(value, callback) {
61449                     taginfo.keys({
61450                         debounce: true,
61451                         geometry: context.geometry(id),
61452                         query: value
61453                     }, function(err, data) {
61454                         if (!err) callback(sort(value, data));
61455                     });
61456                 }));
61457
61458             value.call(d3combobox()
61459                 .fetcher(function(value, callback) {
61460                     taginfo.values({
61461                         debounce: true,
61462                         key: utilGetSetValue(key),
61463                         geometry: context.geometry(id),
61464                         query: value
61465                     }, function(err, data) {
61466                         if (!err) callback(sort(value, data));
61467                     });
61468                 }));
61469         }
61470
61471
61472         function unbind() {
61473             var row = select(this);
61474
61475             row.selectAll('input.key')
61476                 .call(d3combobox.off);
61477
61478             row.selectAll('input.value')
61479                 .call(d3combobox.off);
61480         }
61481
61482
61483         function keyChange(d) {
61484             var kOld = d.key,
61485                 kNew = this.value.trim(),
61486                 tag = {};
61487
61488             if (kNew && kNew !== kOld) {
61489                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
61490                     base = match[1],
61491                     suffix = +(match[2] || 1);
61492                 while (tags[kNew]) {  // rename key if already in use
61493                     kNew = base + '_' + suffix++;
61494                 }
61495             }
61496             tag[kOld] = undefined;
61497             tag[kNew] = d.value;
61498             d.key = kNew; // Maintain DOM identity through the subsequent update.
61499             this.value = kNew;
61500             dispatch$$1.call('change', this, tag);
61501         }
61502
61503
61504         function valueChange(d) {
61505             var tag = {};
61506             tag[d.key] = this.value;
61507             dispatch$$1.call('change', this, tag);
61508         }
61509
61510
61511         function removeTag(d) {
61512             var tag = {};
61513             tag[d.key] = undefined;
61514             dispatch$$1.call('change', this, tag);
61515             select(this.parentNode).remove();
61516         }
61517
61518
61519         function addTag() {
61520             // Wrapped in a setTimeout in case it's being called from a blur
61521             // handler. Without the setTimeout, the call to `content` would
61522             // wipe out the pending value change.
61523             setTimeout(function() {
61524                 showBlank = true;
61525                 content(wrap);
61526                 list.selectAll('li:last-child input.key').node().focus();
61527             }, 0);
61528         }
61529     }
61530
61531
61532     rawTagEditor.state = function(_) {
61533         if (!arguments.length) return state;
61534         state = _;
61535         return rawTagEditor;
61536     };
61537
61538
61539     rawTagEditor.preset = function(_) {
61540         if (!arguments.length) return preset;
61541         preset = _;
61542         return rawTagEditor;
61543     };
61544
61545
61546     rawTagEditor.tags = function(_) {
61547         if (!arguments.length) return tags;
61548         tags = _;
61549         return rawTagEditor;
61550     };
61551
61552
61553     rawTagEditor.entityID = function(_) {
61554         if (!arguments.length) return id;
61555         id = _;
61556         return rawTagEditor;
61557     };
61558
61559
61560     return utilRebind(rawTagEditor, dispatch$$1, 'on');
61561 }
61562
61563 function uiFieldCheck(field) {
61564     var dispatch$$1 = dispatch('change'),
61565         options = field.strings && field.strings.options,
61566         values$$1 = [],
61567         texts = [],
61568         input = select(null),
61569         text$$1 = select(null),
61570         label = select(null),
61571         entity, value;
61572
61573     if (options) {
61574         for (var k in options) {
61575             values$$1.push(k === 'undefined' ? undefined : k);
61576             texts.push(field.t('options.' + k, { 'default': options[k] }));
61577         }
61578     } else {
61579         values$$1 = [undefined, 'yes'];
61580         texts = [t('inspector.unknown'), t('inspector.check.yes')];
61581         if (field.type === 'check') {
61582             values$$1.push('no');
61583             texts.push(t('inspector.check.no'));
61584         }
61585     }
61586
61587
61588     var check = function(selection$$1) {
61589         // hack: pretend oneway field is a oneway_yes field
61590         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
61591         if (field.id === 'oneway') {
61592             for (var key in entity.tags) {
61593                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
61594                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
61595                     break;
61596                 }
61597             }
61598         }
61599
61600         selection$$1.classed('checkselect', 'true');
61601
61602         label = selection$$1.selectAll('.preset-input-wrap')
61603             .data([0]);
61604
61605         var enter = label.enter()
61606             .append('label')
61607             .attr('class', 'preset-input-wrap');
61608
61609         enter
61610             .append('input')
61611             .property('indeterminate', field.type === 'check')
61612             .attr('type', 'checkbox')
61613             .attr('id', 'preset-input-' + field.id);
61614
61615         enter
61616             .append('span')
61617             .text(texts[0])
61618             .attr('class', 'value');
61619
61620         label = label.merge(enter);
61621         input = label.selectAll('input');
61622         text$$1 = label.selectAll('span.value');
61623
61624         input
61625             .on('click', function() {
61626                 var t$$1 = {};
61627                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
61628                 dispatch$$1.call('change', this, t$$1);
61629                 event.stopPropagation();
61630             });
61631     };
61632
61633
61634     check.entity = function(_) {
61635         if (!arguments.length) return entity;
61636         entity = _;
61637         return check;
61638     };
61639
61640
61641     check.tags = function(tags) {
61642         value = tags[field.key];
61643         input.property('indeterminate', field.type === 'check' && !value);
61644         input.property('checked', value === 'yes');
61645         text$$1.text(texts[values$$1.indexOf(value)]);
61646         label.classed('set', !!value);
61647     };
61648
61649
61650     check.focus = function() {
61651         input.node().focus();
61652     };
61653
61654     return utilRebind(check, dispatch$$1, 'on');
61655 }
61656
61657 function uiFieldCombo(field, context) {
61658     var dispatch$$1 = dispatch('change'),
61659         nominatim = services.geocoder,
61660         taginfo = services.taginfo,
61661         isMulti = (field.type === 'multiCombo'),
61662         isNetwork = (field.type === 'networkCombo'),
61663         optstrings = field.strings && field.strings.options,
61664         optarray = field.options,
61665         snake_case = (field.snake_case || (field.snake_case === undefined)),
61666         combobox = d3combobox().minItems(isMulti ? 1 : 2),
61667         comboData = [],
61668         multiData = [],
61669         container,
61670         input,
61671         entity,
61672         country;
61673
61674     // ensure multiCombo field.key ends with a ':'
61675     if (isMulti && field.key.match(/:$/) === null) {
61676         field.key += ':';
61677     }
61678
61679
61680     function snake(s) {
61681         return s.replace(/\s+/g, '_');
61682     }
61683
61684     function unsnake(s) {
61685         return s.replace(/_+/g, ' ');
61686     }
61687
61688     function clean(s) {
61689         return s.split(';')
61690             .map(function(s) { return s.trim(); })
61691             .join(';');
61692     }
61693
61694
61695     // returns the tag value for a display value
61696     // (for multiCombo, dval should be the key suffix, not the entire key)
61697     function tagValue(dval) {
61698         dval = clean(dval || '');
61699
61700         if (optstrings) {
61701             var match = lodash.find(comboData, function(o) {
61702                 return o.key && clean(o.value) === dval;
61703             });
61704             if (match) {
61705                 return match.key;
61706             }
61707         }
61708
61709         if (field.type === 'typeCombo' && !dval) {
61710             return 'yes';
61711         }
61712
61713         return (snake_case ? snake(dval) : dval) || undefined;
61714     }
61715
61716
61717     // returns the display value for a tag value
61718     // (for multiCombo, tval should be the key suffix, not the entire key)
61719     function displayValue(tval) {
61720         tval = tval || '';
61721
61722         if (optstrings) {
61723             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
61724             if (match) {
61725                 return match.value;
61726             }
61727         }
61728
61729         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
61730             return '';
61731         }
61732
61733         return snake_case ? unsnake(tval) : tval;
61734     }
61735
61736
61737     function objectDifference(a, b) {
61738         return lodash.reject(a, function(d1) {
61739             return lodash.some(b, function(d2) { return d1.value === d2.value; });
61740         });
61741     }
61742
61743
61744     function initCombo(selection$$1, attachTo) {
61745         if (optstrings) {
61746             selection$$1.attr('readonly', 'readonly');
61747             selection$$1.call(combobox, attachTo);
61748             setStaticValues(setPlaceholder);
61749
61750         } else if (optarray) {
61751             selection$$1.call(combobox, attachTo);
61752             setStaticValues(setPlaceholder);
61753
61754         } else if (taginfo) {
61755             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
61756             setTaginfoValues('', setPlaceholder);
61757         }
61758     }
61759
61760
61761     function setStaticValues(callback) {
61762         if (!(optstrings || optarray)) return;
61763
61764         if (optstrings) {
61765             comboData = Object.keys(optstrings).map(function(k) {
61766                 var v = field.t('options.' + k, { 'default': optstrings[k] });
61767                 return {
61768                     key: k,
61769                     value: v,
61770                     title: v
61771                 };
61772             });
61773
61774         } else if (optarray) {
61775             comboData = optarray.map(function(k) {
61776                 var v = snake_case ? unsnake(k) : k;
61777                 return {
61778                     key: k,
61779                     value: v,
61780                     title: v
61781                 };
61782             });
61783         }
61784
61785         combobox.data(objectDifference(comboData, multiData));
61786         if (callback) callback(comboData);
61787     }
61788
61789
61790     function setTaginfoValues(q, callback) {
61791         var fn = isMulti ? 'multikeys' : 'values';
61792         var query = (isMulti ? field.key : '') + q;
61793         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
61794         if (hasCountryPrefix) {
61795             query = country + ':';
61796         }
61797         taginfo[fn]({
61798             debounce: true,
61799             key: field.key,
61800             geometry: context.geometry(entity.id),
61801             query: query
61802         }, function(err, data) {
61803             if (err) return;
61804             if (hasCountryPrefix) {
61805                 data = lodash.filter(data, function(d) {
61806                     return d.value.toLowerCase().indexOf(country + ':') === 0;
61807                 });
61808             }
61809             comboData = lodash.map(data, function(d) {
61810                 var k = d.value;
61811                 if (isMulti) k = k.replace(field.key, '');
61812                 var v = snake_case ? unsnake(k) : k;
61813                 return {
61814                     key: k,
61815                     value: v,
61816                     title: isMulti ? v : d.title
61817                 };
61818             });
61819             comboData = objectDifference(comboData, multiData);
61820             if (callback) callback(comboData);
61821         });
61822     }
61823
61824
61825     function setPlaceholder(d) {
61826         var ph;
61827         if (isMulti) {
61828             ph = field.placeholder() || t('inspector.add');
61829         } else {
61830             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
61831                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
61832             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
61833         }
61834
61835         container.selectAll('input')
61836             .attr('placeholder', ph + '…');
61837     }
61838
61839
61840     function change() {
61841         var val = tagValue(utilGetSetValue(input)),
61842             t$$1 = {};
61843
61844         if (isMulti) {
61845             if (!val) return;
61846             container.classed('active', false);
61847             utilGetSetValue(input, '');
61848             field.keys.push(field.key + val);
61849             t$$1[field.key + val] = 'yes';
61850             window.setTimeout(function() { input.node().focus(); }, 10);
61851
61852         } else {
61853             t$$1[field.key] = val;
61854         }
61855
61856         dispatch$$1.call('change', this, t$$1);
61857     }
61858
61859
61860     function removeMultikey(d) {
61861         event.stopPropagation();
61862         var t$$1 = {};
61863         t$$1[d.key] = undefined;
61864         dispatch$$1.call('change', this, t$$1);
61865     }
61866
61867
61868     function combo(selection$$1) {
61869         if (isMulti) {
61870             container = selection$$1.selectAll('ul').data([0]);
61871
61872             container = container.enter()
61873                 .append('ul')
61874                 .attr('class', 'form-field-multicombo')
61875                 .on('click', function() {
61876                     window.setTimeout(function() { input.node().focus(); }, 10);
61877                 })
61878                 .merge(container);
61879
61880         } else {
61881             container = selection$$1;
61882         }
61883
61884         input = container.selectAll('input')
61885             .data([0]);
61886
61887         input = input.enter()
61888             .append('input')
61889             .attr('type', 'text')
61890             .attr('id', 'preset-input-' + field.id)
61891             .call(initCombo, selection$$1)
61892             .merge(input);
61893
61894         if (isNetwork && nominatim && entity) {
61895             var center = entity.extent(context.graph()).center();
61896             nominatim.countryCode(center, function (err, code) {
61897                 country = code;
61898             });
61899         }
61900
61901         input
61902             .on('change', change)
61903             .on('blur', change);
61904
61905         if (isMulti) {
61906             combobox
61907                 .on('accept', function() {
61908                     input.node().blur();
61909                     input.node().focus();
61910                 });
61911
61912             input
61913                 .on('focus', function() { container.classed('active', true); });
61914         }
61915     }
61916
61917
61918     combo.tags = function(tags) {
61919         if (isMulti) {
61920             multiData = [];
61921
61922             // Build multiData array containing keys already set..
61923             Object.keys(tags).forEach(function(key) {
61924                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
61925
61926                 var suffix = key.substring(field.key.length);
61927                 multiData.push({
61928                     key: key,
61929                     value: displayValue(suffix)
61930                 });
61931             });
61932
61933             // Set keys for form-field modified (needed for undo and reset buttons)..
61934             field.keys = lodash.map(multiData, 'key');
61935
61936             // Exclude existing multikeys from combo options..
61937             var available = objectDifference(comboData, multiData);
61938             combobox.data(available);
61939
61940             // Hide 'Add' button if this field uses fixed set of
61941             // translateable optstrings and they're all currently used..
61942             container.selectAll('.combobox-input, .combobox-caret')
61943                 .classed('hide', optstrings && !available.length);
61944
61945
61946             // Render chips
61947             var chips = container.selectAll('.chips')
61948                 .data(multiData);
61949
61950             chips.exit()
61951                 .remove();
61952
61953             var enter = chips.enter()
61954                 .insert('li', 'input')
61955                 .attr('class', 'chips');
61956
61957             enter.append('span');
61958             enter.append('a');
61959
61960             chips = chips.merge(enter);
61961
61962             chips.select('span')
61963                 .text(function(d) { return d.value; });
61964
61965             chips.select('a')
61966                 .on('click', removeMultikey)
61967                 .attr('class', 'remove')
61968                 .text('×');
61969
61970         } else {
61971             utilGetSetValue(input, displayValue(tags[field.key]));
61972         }
61973     };
61974
61975
61976     combo.focus = function() {
61977         input.node().focus();
61978     };
61979
61980
61981     combo.entity = function(_) {
61982         if (!arguments.length) return entity;
61983         entity = _;
61984         return combo;
61985     };
61986
61987
61988     return utilRebind(combo, dispatch$$1, 'on');
61989 }
61990
61991 function uiFieldText(field, context) {
61992     var dispatch$$1 = dispatch('change'),
61993         nominatim = services.geocoder,
61994         input,
61995         entity;
61996
61997
61998     function i(selection$$1) {
61999         var fieldId = 'preset-input-' + field.id;
62000
62001         input = selection$$1.selectAll('input')
62002             .data([0]);
62003
62004         input = input.enter()
62005             .append('input')
62006             .attr('type', field.type)
62007             .attr('id', fieldId)
62008             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62009             .merge(input);
62010
62011         input
62012             .on('input', change(true))
62013             .on('blur', change())
62014             .on('change', change());
62015
62016         if (field.type === 'tel' && nominatim && entity) {
62017             var center = entity.extent(context.graph()).center();
62018             nominatim.countryCode(center, function (err, countryCode) {
62019                 if (err || !dataPhoneFormats[countryCode]) return;
62020                 selection$$1.selectAll('#' + fieldId)
62021                     .attr('placeholder', dataPhoneFormats[countryCode]);
62022             });
62023
62024         } else if (field.type === 'number') {
62025             input.attr('type', 'text');
62026
62027             var spinControl = selection$$1.selectAll('.spin-control')
62028                 .data([0]);
62029
62030             var enter = spinControl.enter()
62031                 .append('div')
62032                 .attr('class', 'spin-control');
62033
62034             enter
62035                 .append('button')
62036                 .datum(1)
62037                 .attr('class', 'increment')
62038                 .attr('tabindex', -1);
62039
62040             enter
62041                 .append('button')
62042                 .datum(-1)
62043                 .attr('class', 'decrement')
62044                 .attr('tabindex', -1);
62045
62046             spinControl = spinControl
62047                 .merge(enter);
62048
62049             spinControl.selectAll('button')
62050                 .on('click', function(d) {
62051                     event.preventDefault();
62052                     var num = parseInt(input.node().value || 0, 10);
62053                     if (!isNaN(num)) input.node().value = num + d;
62054                     change()();
62055                 });
62056         }
62057     }
62058
62059
62060     function change(onInput) {
62061         return function() {
62062             var t$$1 = {};
62063             t$$1[field.key] = utilGetSetValue(input) || undefined;
62064             dispatch$$1.call('change', this, t$$1, onInput);
62065         };
62066     }
62067
62068
62069     i.entity = function(_) {
62070         if (!arguments.length) return entity;
62071         entity = _;
62072         return i;
62073     };
62074
62075
62076     i.tags = function(tags) {
62077         utilGetSetValue(input, tags[field.key] || '');
62078     };
62079
62080
62081     i.focus = function() {
62082         var node = input.node();
62083         if (node) node.focus();
62084     };
62085
62086     return utilRebind(i, dispatch$$1, 'on');
62087 }
62088
62089 function uiFieldAccess(field) {
62090     var dispatch$$1 = dispatch('change'),
62091         items;
62092
62093     function access(selection$$1) {
62094         var wrap = selection$$1.selectAll('.preset-input-wrap')
62095             .data([0]);
62096
62097         wrap = wrap.enter()
62098             .append('div')
62099             .attr('class', 'cf preset-input-wrap')
62100             .append('ul')
62101             .merge(wrap);
62102
62103         var list = wrap.selectAll('ul')
62104             .data([0]);
62105
62106         list = list.enter()
62107             .append('ul')
62108             .merge(list);
62109
62110
62111         items = list.selectAll('li')
62112             .data(field.keys);
62113
62114         // Enter
62115         var enter = items.enter()
62116             .append('li')
62117             .attr('class', function(d) { return 'cf preset-access-' + d; });
62118
62119         enter
62120             .append('span')
62121             .attr('class', 'col6 label preset-label-access')
62122             .attr('for', function(d) { return 'preset-input-access-' + d; })
62123             .text(function(d) { return field.t('types.' + d); });
62124
62125         enter
62126             .append('div')
62127             .attr('class', 'col6 preset-input-access-wrap')
62128             .append('input')
62129             .attr('type', 'text')
62130             .attr('class', 'preset-input-access')
62131             .attr('id', function(d) { return 'preset-input-access-' + d; })
62132             .each(function(d) {
62133                 select(this)
62134                     .call(d3combobox()
62135                         .data(access.options(d)));
62136             });
62137
62138
62139         // Update
62140         items = items.merge(enter);
62141
62142         wrap.selectAll('.preset-input-access')
62143             .on('change', change)
62144             .on('blur', change);
62145     }
62146
62147
62148     function change(d) {
62149         var tag = {};
62150         tag[d] = utilGetSetValue(select(this)) || undefined;
62151         dispatch$$1.call('change', this, tag);
62152     }
62153
62154
62155     access.options = function(type) {
62156         var options = ['no', 'permissive', 'private', 'destination'];
62157
62158         if (type !== 'access') {
62159             options.unshift('yes');
62160             options.push('designated');
62161
62162             if (type === 'bicycle') {
62163                 options.push('dismount');
62164             }
62165         }
62166
62167         return options.map(function(option) {
62168             return {
62169                 title: field.t('options.' + option + '.description'),
62170                 value: option
62171             };
62172         });
62173     };
62174
62175
62176     var placeholders = {
62177         footway: {
62178             foot: 'designated',
62179             motor_vehicle: 'no'
62180         },
62181         steps: {
62182             foot: 'yes',
62183             motor_vehicle: 'no',
62184             bicycle: 'no',
62185             horse: 'no'
62186         },
62187         pedestrian: {
62188             foot: 'yes',
62189             motor_vehicle: 'no'
62190         },
62191         cycleway: {
62192             motor_vehicle: 'no',
62193             bicycle: 'designated'
62194         },
62195         bridleway: {
62196             motor_vehicle: 'no',
62197             horse: 'designated'
62198         },
62199         path: {
62200             foot: 'yes',
62201             motor_vehicle: 'no',
62202             bicycle: 'yes',
62203             horse: 'yes'
62204         },
62205         motorway: {
62206             foot: 'no',
62207             motor_vehicle: 'yes',
62208             bicycle: 'no',
62209             horse: 'no'
62210         },
62211         trunk: {
62212             motor_vehicle: 'yes'
62213         },
62214         primary: {
62215             foot: 'yes',
62216             motor_vehicle: 'yes',
62217             bicycle: 'yes',
62218             horse: 'yes'
62219         },
62220         secondary: {
62221             foot: 'yes',
62222             motor_vehicle: 'yes',
62223             bicycle: 'yes',
62224             horse: 'yes'
62225         },
62226         tertiary: {
62227             foot: 'yes',
62228             motor_vehicle: 'yes',
62229             bicycle: 'yes',
62230             horse: 'yes'
62231         },
62232         residential: {
62233             foot: 'yes',
62234             motor_vehicle: 'yes',
62235             bicycle: 'yes',
62236             horse: 'yes'
62237         },
62238         unclassified: {
62239             foot: 'yes',
62240             motor_vehicle: 'yes',
62241             bicycle: 'yes',
62242             horse: 'yes'
62243         },
62244         service: {
62245             foot: 'yes',
62246             motor_vehicle: 'yes',
62247             bicycle: 'yes',
62248             horse: 'yes'
62249         },
62250         motorway_link: {
62251             foot: 'no',
62252             motor_vehicle: 'yes',
62253             bicycle: 'no',
62254             horse: 'no'
62255         },
62256         trunk_link: {
62257             motor_vehicle: 'yes'
62258         },
62259         primary_link: {
62260             foot: 'yes',
62261             motor_vehicle: 'yes',
62262             bicycle: 'yes',
62263             horse: 'yes'
62264         },
62265         secondary_link: {
62266             foot: 'yes',
62267             motor_vehicle: 'yes',
62268             bicycle: 'yes',
62269             horse: 'yes'
62270         },
62271         tertiary_link: {
62272             foot: 'yes',
62273             motor_vehicle: 'yes',
62274             bicycle: 'yes',
62275             horse: 'yes'
62276         }
62277     };
62278
62279
62280     access.tags = function(tags) {
62281         utilGetSetValue(items.selectAll('.preset-input-access'),
62282             function(d) { return tags[d] || ''; })
62283             .attr('placeholder', function() {
62284                 return tags.access ? tags.access : field.placeholder();
62285             });
62286
62287         items.selectAll('#preset-input-access-access')
62288             .attr('placeholder', 'yes');
62289
62290         lodash.forEach(placeholders[tags.highway], function(v, k) {
62291             items.selectAll('#preset-input-access-' + k)
62292                 .attr('placeholder', function() { return (tags.access || v); });
62293         });
62294     };
62295
62296
62297     access.focus = function() {
62298         items.selectAll('.preset-input-access')
62299             .node().focus();
62300     };
62301
62302
62303     return utilRebind(access, dispatch$$1, 'on');
62304 }
62305
62306 function uiFieldAddress(field, context) {
62307     var dispatch$$1 = dispatch('init', 'change'),
62308         nominatim = services.geocoder,
62309         wrap = select(null),
62310         isInitialized = false,
62311         entity;
62312
62313     function getNearStreets() {
62314         var extent$$1 = entity.extent(context.graph()),
62315             l = extent$$1.center(),
62316             box = geoExtent$$1(l).padByMeters(200);
62317
62318         var streets = context.intersects(box)
62319             .filter(isAddressable)
62320             .map(function(d) {
62321                 var loc = context.projection([
62322                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
62323                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
62324                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
62325                 return {
62326                     title: d.tags.name,
62327                     value: d.tags.name,
62328                     dist: choice.distance
62329                 };
62330             })
62331             .sort(function(a, b) {
62332                 return a.dist - b.dist;
62333             });
62334
62335         return lodash.uniqBy(streets, 'value');
62336
62337         function isAddressable(d) {
62338             return d.tags.highway && d.tags.name && d.type === 'way';
62339         }
62340     }
62341
62342
62343     function getNearCities() {
62344         var extent$$1 = entity.extent(context.graph()),
62345             l = extent$$1.center(),
62346             box = geoExtent$$1(l).padByMeters(200);
62347
62348         var cities = context.intersects(box)
62349             .filter(isAddressable)
62350             .map(function(d) {
62351                 return {
62352                     title: d.tags['addr:city'] || d.tags.name,
62353                     value: d.tags['addr:city'] || d.tags.name,
62354                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62355                 };
62356             })
62357             .sort(function(a, b) {
62358                 return a.dist - b.dist;
62359             });
62360
62361         return lodash.uniqBy(cities, 'value');
62362
62363
62364         function isAddressable(d) {
62365             if (d.tags.name &&
62366                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
62367                 return true;
62368
62369             if (d.tags.place && d.tags.name && (
62370                     d.tags.place === 'city' ||
62371                     d.tags.place === 'town' ||
62372                     d.tags.place === 'village'))
62373                 return true;
62374
62375             if (d.tags['addr:city']) return true;
62376
62377             return false;
62378         }
62379     }
62380
62381     function getNearValues(key) {
62382         var extent$$1 = entity.extent(context.graph()),
62383             l = extent$$1.center(),
62384             box = geoExtent$$1(l).padByMeters(200);
62385
62386         var results = context.intersects(box)
62387             .filter(function hasTag(d) {
62388                 return d.tags[key];
62389             })
62390             .map(function(d) {
62391                 return {
62392                     title: d.tags[key],
62393                     value: d.tags[key],
62394                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
62395                 };
62396             })
62397             .sort(function(a, b) {
62398                 return a.dist - b.dist;
62399             });
62400
62401         return lodash.uniqBy(results, 'value');
62402     }
62403
62404
62405     function initCallback(err, countryCode) {
62406         if (err) return;
62407
62408         var addressFormat = lodash.find(dataAddressFormats, function (a) {
62409             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
62410         }) || lodash.first(dataAddressFormats);
62411
62412         var widths = addressFormat.widths || {
62413             housenumber: 1/3, street: 2/3,
62414             city: 2/3, state: 1/4, postcode: 1/3
62415         };
62416
62417         function row(r) {
62418             // Normalize widths.
62419             var total = lodash.reduce(r, function(sum$$1, field) {
62420                 return sum$$1 + (widths[field] || 0.5);
62421             }, 0);
62422
62423             return r.map(function (field) {
62424                 return {
62425                     id: field,
62426                     width: (widths[field] || 0.5) / total
62427                 };
62428             });
62429         }
62430
62431         wrap.selectAll('div.addr-row')
62432             .data(addressFormat.format)
62433             .enter()
62434             .append('div')
62435             .attr('class', 'addr-row')
62436             .selectAll('input')
62437             .data(row)
62438             .enter()
62439             .append('input')
62440             .property('type', 'text')
62441             .attr('placeholder', function (d) {
62442                 var localkey = d.id + '!' + countryCode,
62443                     tkey = field.strings.placeholders[localkey] ? localkey : d.id;
62444                 return field.t('placeholders.' + tkey);
62445             })
62446             .attr('class', function (d) { return 'addr-' + d.id; })
62447             .style('width', function (d) { return d.width * 100 + '%'; });
62448
62449         // Update
62450
62451         // setup dropdowns for common address tags
62452         var dropdowns = addressFormat.dropdowns || [
62453             'city', 'county', 'country', 'district', 'hamlet',
62454             'neighbourhood', 'place', 'postcode', 'province',
62455             'quarter', 'state', 'street', 'subdistrict', 'suburb'
62456         ];
62457
62458         // If fields exist for any of these tags, create dropdowns to pick nearby values..
62459         dropdowns.forEach(function(tag) {
62460             var nearValues = (tag === 'street') ? getNearStreets
62461                     : (tag === 'city') ? getNearCities
62462                     : getNearValues;
62463
62464             wrap.selectAll('input.addr-' + tag)
62465                 .call(d3combobox()
62466                     .minItems(1)
62467                     .fetcher(function(value, callback) {
62468                         callback(nearValues('addr:' + tag));
62469                     }));
62470         });
62471
62472         wrap.selectAll('input')
62473             .on('blur', change())
62474             .on('change', change());
62475
62476         wrap.selectAll('input:not(.combobox-input)')
62477             .on('input', change(true));
62478
62479         dispatch$$1.call('init');
62480         isInitialized = true;
62481     }
62482
62483
62484     function address(selection$$1) {
62485         isInitialized = false;
62486
62487         wrap = selection$$1.selectAll('.preset-input-wrap')
62488             .data([0]);
62489
62490         wrap = wrap.enter()
62491             .append('div')
62492             .attr('class', 'preset-input-wrap')
62493             .merge(wrap);
62494
62495         if (nominatim && entity) {
62496             var center = entity.extent(context.graph()).center();
62497             nominatim.countryCode(center, initCallback);
62498         }
62499     }
62500
62501
62502     function change(onInput) {
62503         return function() {
62504             var tags = {};
62505
62506             wrap.selectAll('input')
62507                 .each(function (field) {
62508                     tags['addr:' + field.id] = this.value || undefined;
62509                 });
62510
62511             dispatch$$1.call('change', this, tags, onInput);
62512         };
62513     }
62514
62515
62516     function updateTags(tags) {
62517         utilGetSetValue(wrap.selectAll('input'), function (field) {
62518             return tags['addr:' + field.id] || '';
62519         });
62520     }
62521
62522
62523     address.entity = function(_) {
62524         if (!arguments.length) return entity;
62525         entity = _;
62526         return address;
62527     };
62528
62529
62530     address.tags = function(tags) {
62531         if (isInitialized) {
62532             updateTags(tags);
62533         } else {
62534             dispatch$$1.on('init', function () {
62535                 dispatch$$1.on('init', null);
62536                 updateTags(tags);
62537             });
62538         }
62539     };
62540
62541
62542     address.focus = function() {
62543         var node = wrap.selectAll('input').node();
62544         if (node) node.focus();
62545     };
62546
62547
62548     return utilRebind(address, dispatch$$1, 'on');
62549 }
62550
62551 function uiFieldCycleway(field) {
62552     var dispatch$$1 = dispatch('change'),
62553         items = select(null);
62554
62555
62556     function cycleway(selection$$1) {
62557
62558         function stripcolon(s) {
62559             return s.replace(':', '');
62560         }
62561
62562
62563         var wrap = selection$$1.selectAll('.preset-input-wrap')
62564             .data([0]);
62565
62566         wrap = wrap.enter()
62567             .append('div')
62568             .attr('class', 'cf preset-input-wrap')
62569             .merge(wrap);
62570
62571
62572         var div = wrap.selectAll('ul')
62573             .data([0]);
62574
62575         div = div.enter()
62576             .append('ul')
62577             .merge(div);
62578
62579
62580         items = div.selectAll('li')
62581             .data(field.keys);
62582
62583         var enter = items.enter()
62584             .append('li')
62585             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
62586
62587         enter
62588             .append('span')
62589             .attr('class', 'col6 label preset-label-cycleway')
62590             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
62591             .text(function(d) { return field.t('types.' + d); });
62592
62593         enter
62594             .append('div')
62595             .attr('class', 'col6 preset-input-cycleway-wrap')
62596             .append('input')
62597             .attr('type', 'text')
62598             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
62599             .each(function(d) {
62600                 select(this).call(d3combobox().data(cycleway.options(d)));
62601             });
62602
62603
62604         // Update
62605         wrap.selectAll('.preset-input-cycleway')
62606             .on('change', change)
62607             .on('blur', change);
62608     }
62609
62610
62611     function change() {
62612         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
62613             right = utilGetSetValue(select('.preset-input-cyclewayright')),
62614             tag = {};
62615
62616         if (left === 'none' || left === '') { left = undefined; }
62617         if (right === 'none' || right === '') { right = undefined; }
62618
62619         // Always set both left and right as changing one can affect the other
62620         tag = {
62621             cycleway: undefined,
62622             'cycleway:left': left,
62623             'cycleway:right': right
62624         };
62625
62626         // If the left and right tags match, use the cycleway tag to tag both
62627         // sides the same way
62628         if (left === right) {
62629             tag = {
62630                 cycleway: left,
62631                 'cycleway:left': undefined,
62632                 'cycleway:right': undefined
62633             };
62634         }
62635
62636         dispatch$$1.call('change', this, tag);
62637     }
62638
62639
62640     cycleway.options = function() {
62641         return keys(field.strings.options).map(function(option) {
62642             return {
62643                 title: field.t('options.' + option + '.description'),
62644                 value: option
62645             };
62646         });
62647     };
62648
62649
62650     cycleway.tags = function(tags) {
62651         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
62652                 // If cycleway is set, always return that
62653                 if (tags.cycleway) {
62654                     return tags.cycleway;
62655                 }
62656                 return tags[d] || '';
62657             })
62658             .attr('placeholder', field.placeholder());
62659     };
62660
62661
62662     cycleway.focus = function() {
62663         items.selectAll('.preset-input-cycleway')
62664             .node().focus();
62665     };
62666
62667
62668     return utilRebind(cycleway, dispatch$$1, 'on');
62669 }
62670
62671 function uiFieldLanes(field, context) {
62672     var dispatch$$1 = dispatch('change'),
62673         LANE_WIDTH = 40,
62674         LANE_HEIGHT = 200,
62675         wayID,
62676         lanesData;
62677
62678     function lanes(selection$$1) {
62679         lanesData = context.entity(wayID).lanes();
62680
62681         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62682             selection$$1.call(lanes.off);
62683             return;
62684         }
62685
62686         var wrap = selection$$1.selectAll('.preset-input-wrap')
62687             .data([0]);
62688
62689         wrap = wrap.enter()
62690             .append('div')
62691             .attr('class', 'preset-input-wrap')
62692             .merge(wrap);
62693
62694         var surface =  wrap.selectAll('.surface')
62695             .data([0]);
62696
62697         var d = utilGetDimensions(wrap);
62698         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
62699
62700         surface = surface.enter()
62701             .append('svg')
62702             .attr('width', d[0])
62703             .attr('height', 300)
62704             .attr('class', 'surface')
62705             .merge(surface);
62706
62707
62708         var lanesSelection = surface.selectAll('.lanes')
62709             .data([0]);
62710
62711         lanesSelection = lanesSelection.enter()
62712             .append('g')
62713             .attr('class', 'lanes')
62714             .merge(lanesSelection);
62715
62716         lanesSelection
62717             .attr('transform', function () {
62718                 return 'translate(' + (freeSpace / 2) + ', 0)';
62719             });
62720
62721
62722         var lane = lanesSelection.selectAll('.lane')
62723            .data(lanesData.lanes);
62724
62725         lane.exit()
62726             .remove();
62727
62728         var enter = lane.enter()
62729             .append('g')
62730             .attr('class', 'lane');
62731
62732         enter
62733             .append('g')
62734             .append('rect')
62735             .attr('y', 50)
62736             .attr('width', LANE_WIDTH)
62737             .attr('height', LANE_HEIGHT);
62738
62739         enter
62740             .append('g')
62741             .attr('class', 'forward')
62742             .append('text')
62743             .attr('y', 40)
62744             .attr('x', 14)
62745             .text('▲');
62746
62747         enter
62748             .append('g')
62749             .attr('class', 'bothways')
62750             .append('text')
62751             .attr('y', 40)
62752             .attr('x', 14)
62753             .text('▲▼');
62754
62755         enter
62756             .append('g')
62757             .attr('class', 'backward')
62758             .append('text')
62759             .attr('y', 40)
62760             .attr('x', 14)
62761             .text('▼');
62762
62763
62764         lane = lane
62765             .merge(enter);
62766
62767         lane
62768             .attr('transform', function(d) {
62769                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
62770             });
62771
62772         lane.select('.forward')
62773             .style('visibility', function(d) {
62774                 return d.direction === 'forward' ? 'visible' : 'hidden';
62775             });
62776
62777         lane.select('.bothways')
62778             .style('visibility', function(d) {
62779                 return d.direction === 'bothways' ? 'visible' : 'hidden';
62780             });
62781
62782         lane.select('.backward')
62783             .style('visibility', function(d) {
62784                 return d.direction === 'backward' ? 'visible' : 'hidden';
62785             });
62786     }
62787
62788
62789     lanes.entity = function(_) {
62790         if (!wayID || wayID !== _.id) {
62791             wayID = _.id;
62792         }
62793     };
62794
62795     lanes.tags = function() {};
62796     lanes.focus = function() {};
62797     lanes.off = function() {};
62798
62799     return utilRebind(lanes, dispatch$$1, 'on');
62800 }
62801
62802 function uiFieldLocalized(field, context) {
62803     var dispatch$$1 = dispatch('change', 'input'),
62804         wikipedia = services.wikipedia,
62805         input = select(null),
62806         localizedInputs = select(null),
62807         wikiTitles,
62808         entity;
62809
62810
62811     function localized(selection$$1) {
62812         input = selection$$1.selectAll('.localized-main')
62813             .data([0]);
62814
62815         input = input.enter()
62816             .append('input')
62817             .attr('type', 'text')
62818             .attr('id', 'preset-input-' + field.id)
62819             .attr('class', 'localized-main')
62820             .attr('placeholder', field.placeholder())
62821             .merge(input);
62822
62823         if (field.id === 'name') {
62824             var preset = context.presets().match(entity, context.graph());
62825             input.call(d3combobox().fetcher(
62826                 utilSuggestNames(preset, dataSuggestions)
62827             ));
62828         }
62829
62830         input
62831             .on('input', change(true))
62832             .on('blur', change())
62833             .on('change', change());
62834
62835
62836         var translateButton = selection$$1.selectAll('.localized-add')
62837             .data([0]);
62838
62839         translateButton = translateButton.enter()
62840             .append('button')
62841             .attr('class', 'button-input-action localized-add minor')
62842             .attr('tabindex', -1)
62843             .call(svgIcon('#icon-plus'))
62844             .call(tooltip()
62845                 .title(t('translate.translate'))
62846                 .placement('left'))
62847             .merge(translateButton);
62848
62849         translateButton
62850             .on('click', addNew);
62851
62852
62853         localizedInputs = selection$$1.selectAll('.localized-wrap')
62854             .data([0]);
62855
62856         localizedInputs = localizedInputs.enter().append('div')
62857             .attr('class', 'localized-wrap')
62858             .merge(localizedInputs);
62859     }
62860
62861
62862     function addNew() {
62863         event.preventDefault();
62864         var data$$1 = localizedInputs.selectAll('div.entry').data();
62865         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
62866         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
62867         var isLangEn = defaultLang.indexOf('en') > -1;
62868         if (isLangEn || langExists) {
62869             defaultLang = '';
62870         }
62871         data$$1.push({ lang: defaultLang, value: '' });
62872         localizedInputs.call(render, data$$1);
62873     }
62874
62875
62876     function change(onInput) {
62877         return function() {
62878             var t$$1 = {};
62879             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
62880             dispatch$$1.call('change', this, t$$1, onInput);
62881         };
62882     }
62883
62884
62885     function key(lang) {
62886         return field.key + ':' + lang;
62887     }
62888
62889
62890     function changeLang(d) {
62891         var lang = utilGetSetValue(select(this)),
62892             t$$1 = {},
62893             language = lodash.find(dataWikipedia, function(d) {
62894                 return d[0].toLowerCase() === lang.toLowerCase() ||
62895                     d[1].toLowerCase() === lang.toLowerCase();
62896             });
62897
62898         if (language) lang = language[2];
62899
62900         if (d.lang && d.lang !== lang) {
62901             t$$1[key(d.lang)] = undefined;
62902         }
62903
62904         var value = utilGetSetValue(select(this.parentNode)
62905             .selectAll('.localized-value'));
62906
62907         if (lang && value) {
62908             t$$1[key(lang)] = value;
62909         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
62910             t$$1[key(lang)] = wikiTitles[d.lang];
62911         }
62912
62913         d.lang = lang;
62914         dispatch$$1.call('change', this, t$$1);
62915     }
62916
62917
62918     function changeValue(d) {
62919         if (!d.lang) return;
62920         var t$$1 = {};
62921         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
62922         dispatch$$1.call('change', this, t$$1);
62923     }
62924
62925
62926     function fetcher(value, cb) {
62927         var v = value.toLowerCase();
62928
62929         cb(dataWikipedia.filter(function(d) {
62930             return d[0].toLowerCase().indexOf(v) >= 0 ||
62931             d[1].toLowerCase().indexOf(v) >= 0 ||
62932             d[2].toLowerCase().indexOf(v) >= 0;
62933         }).map(function(d) {
62934             return { value: d[1] };
62935         }));
62936     }
62937
62938
62939     function render(selection$$1, data$$1) {
62940         var wraps = selection$$1.selectAll('div.entry').
62941             data(data$$1, function(d) { return d.lang; });
62942
62943         wraps.exit()
62944             .transition()
62945             .duration(200)
62946             .style('max-height','0px')
62947             .style('opacity', '0')
62948             .style('top','-10px')
62949             .remove();
62950
62951         var innerWrap = wraps.enter()
62952             .insert('div', ':first-child');
62953
62954         innerWrap.attr('class', 'entry')
62955             .each(function() {
62956                 var wrap = select(this);
62957                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
62958
62959                 var label = wrap
62960                     .append('label')
62961                     .attr('class','form-label')
62962                     .text(t('translate.localized_translation_label'))
62963                     .attr('for','localized-lang');
62964
62965                 label
62966                     .append('button')
62967                     .attr('class', 'minor remove')
62968                     .on('click', function(d){
62969                         event.preventDefault();
62970                         var t$$1 = {};
62971                         t$$1[key(d.lang)] = undefined;
62972                         dispatch$$1.call('change', this, t$$1);
62973                         select(this.parentNode.parentNode)
62974                             .style('top','0')
62975                             .style('max-height','240px')
62976                             .transition()
62977                             .style('opacity', '0')
62978                             .style('max-height','0px')
62979                             .remove();
62980                     })
62981                     .call(svgIcon('#operation-delete'));
62982
62983                 wrap
62984                     .append('input')
62985                     .attr('class', 'localized-lang')
62986                     .attr('type', 'text')
62987                     .attr('placeholder',t('translate.localized_translation_language'))
62988                     .on('blur', changeLang)
62989                     .on('change', changeLang)
62990                     .call(langcombo);
62991
62992                 wrap
62993                     .append('input')
62994                     .on('blur', changeValue)
62995                     .on('change', changeValue)
62996                     .attr('type', 'text')
62997                     .attr('placeholder', t('translate.localized_translation_name'))
62998                     .attr('class', 'localized-value');
62999             });
63000
63001         innerWrap
63002             .style('margin-top', '0px')
63003             .style('max-height', '0px')
63004             .style('opacity', '0')
63005             .transition()
63006             .duration(200)
63007             .style('margin-top', '10px')
63008             .style('max-height', '240px')
63009             .style('opacity', '1')
63010             .on('end', function() {
63011                 select(this)
63012                     .style('max-height', '')
63013                     .style('overflow', 'visible');
63014             });
63015
63016
63017         var entry = selection$$1.selectAll('.entry');
63018
63019         utilGetSetValue(entry.select('.localized-lang'), function(d) {
63020                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
63021                 return lang ? lang[1] : d.lang;
63022             });
63023
63024         utilGetSetValue(entry.select('.localized-value'),
63025             function(d) { return d.value; });
63026     }
63027
63028
63029     localized.tags = function(tags) {
63030         // Fetch translations from wikipedia
63031         if (tags.wikipedia && !wikiTitles) {
63032             wikiTitles = {};
63033             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
63034             if (wm && wm[0] && wm[1]) {
63035                 wikipedia.translations(wm[1], wm[2], function(d) {
63036                     wikiTitles = d;
63037                 });
63038             }
63039         }
63040
63041         utilGetSetValue(input, tags[field.key] || '');
63042
63043         var postfixed = [], k, m;
63044         for (k in tags) {
63045             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
63046             if (m && m[1] === field.key && m[2]) {
63047                 postfixed.push({ lang: m[2], value: tags[k] });
63048             }
63049         }
63050
63051         localizedInputs.call(render, postfixed.reverse());
63052     };
63053
63054
63055     localized.focus = function() {
63056         input.node().focus();
63057     };
63058
63059
63060     localized.entity = function(_) {
63061         if (!arguments.length) return entity;
63062         entity = _;
63063         return localized;
63064     };
63065
63066     return utilRebind(localized, dispatch$$1, 'on');
63067 }
63068
63069 function uiFieldMaxspeed(field, context) {
63070     var dispatch$$1 = dispatch('change'),
63071         entity,
63072         isImperial,
63073         unitInput = select(null),
63074         input = select(null),
63075         combobox;
63076
63077     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
63078         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
63079
63080
63081     function maxspeed(selection$$1) {
63082         combobox = d3combobox();
63083         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
63084
63085         input = selection$$1.selectAll('#preset-input-' + field.id)
63086             .data([0]);
63087
63088         input = input.enter()
63089             .append('input')
63090             .attr('type', 'text')
63091             .attr('id', 'preset-input-' + field.id)
63092             .attr('placeholder', field.placeholder())
63093             .call(combobox)
63094             .merge(input);
63095
63096         input
63097             .on('change', change)
63098             .on('blur', change);
63099
63100         var childNodes = context.graph().childNodes(context.entity(entity.id)),
63101             loc = childNodes[~~(childNodes.length/2)].loc;
63102
63103         isImperial = lodash.some(dataImperial.features, function(f) {
63104             return lodash.some(f.geometry.coordinates, function(d) {
63105                 return geoPointInPolygon(loc, d);
63106             });
63107         });
63108
63109         unitInput = selection$$1.selectAll('input.maxspeed-unit')
63110             .data([0]);
63111
63112         unitInput = unitInput.enter()
63113             .append('input')
63114             .attr('type', 'text')
63115             .attr('class', 'maxspeed-unit')
63116             .call(unitCombobox)
63117             .merge(unitInput);
63118
63119         unitInput
63120             .on('blur', changeUnits)
63121             .on('change', changeUnits);
63122
63123
63124         function changeUnits() {
63125             isImperial = utilGetSetValue(unitInput) === 'mph';
63126             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63127             setSuggestions();
63128             change();
63129         }
63130     }
63131
63132
63133     function setSuggestions() {
63134         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
63135         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
63136     }
63137
63138
63139     function comboValues(d) {
63140         return {
63141             value: d.toString(),
63142             title: d.toString()
63143         };
63144     }
63145
63146
63147     function change() {
63148         var tag = {},
63149             value = utilGetSetValue(input);
63150
63151         if (!value) {
63152             tag[field.key] = undefined;
63153         } else if (isNaN(value) || !isImperial) {
63154             tag[field.key] = value;
63155         } else {
63156             tag[field.key] = value + ' mph';
63157         }
63158
63159         dispatch$$1.call('change', this, tag);
63160     }
63161
63162
63163     maxspeed.tags = function(tags) {
63164         var value = tags[field.key];
63165
63166         if (value && value.indexOf('mph') >= 0) {
63167             value = parseInt(value, 10);
63168             isImperial = true;
63169         } else if (value) {
63170             isImperial = false;
63171         }
63172
63173         setSuggestions();
63174         utilGetSetValue(input, value || '');
63175     };
63176
63177
63178     maxspeed.focus = function() {
63179         input.node().focus();
63180     };
63181
63182
63183     maxspeed.entity = function(_) {
63184         entity = _;
63185     };
63186
63187
63188     return utilRebind(maxspeed, dispatch$$1, 'on');
63189 }
63190
63191 function uiFieldRadio(field) {
63192     var dispatch$$1 = dispatch('change'),
63193         placeholder = select(null),
63194         labels = select(null),
63195         radios = select(null);
63196
63197
63198     function radio(selection$$1) {
63199         selection$$1.classed('preset-radio', true);
63200
63201         var wrap = selection$$1.selectAll('.preset-input-wrap')
63202             .data([0]);
63203
63204         var enter = wrap.enter()
63205             .append('div')
63206             .attr('class', 'preset-input-wrap toggle-list');
63207
63208         enter
63209             .append('span')
63210             .attr('class', 'placeholder');
63211
63212         wrap = wrap
63213             .merge(enter);
63214
63215
63216         placeholder = wrap.selectAll('.placeholder');
63217
63218         labels = wrap.selectAll('label')
63219             .data(field.options || field.keys);
63220
63221         enter = labels.enter()
63222             .append('label');
63223
63224         enter.append('input')
63225             .attr('type', 'radio')
63226             .attr('name', field.id)
63227             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
63228             .attr('checked', false);
63229
63230         enter.append('span')
63231             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
63232
63233         labels = labels
63234             .merge(enter);
63235
63236         radios = labels.selectAll('input')
63237             .on('change', change);
63238     }
63239
63240
63241     function change() {
63242         var t$$1 = {};
63243         if (field.key) t$$1[field.key] = undefined;
63244         radios.each(function(d) {
63245             var active$$1 = select(this).property('checked');
63246             if (field.key) {
63247                 if (active$$1) t$$1[field.key] = d;
63248             } else {
63249                 t$$1[d] = active$$1 ? 'yes' : undefined;
63250             }
63251         });
63252         dispatch$$1.call('change', this, t$$1);
63253     }
63254
63255
63256     radio.tags = function(tags) {
63257         function checked(d) {
63258             if (field.key) {
63259                 return tags[field.key] === d;
63260             } else {
63261                 return !!(tags[d] && tags[d] !== 'no');
63262             }
63263         }
63264
63265         labels.classed('active', checked);
63266         radios.property('checked', checked);
63267         var selection$$1 = radios.filter(function() { return this.checked; });
63268         if (selection$$1.empty()) {
63269             placeholder.text(t('inspector.none'));
63270         } else {
63271             placeholder.text(selection$$1.attr('value'));
63272         }
63273     };
63274
63275
63276     radio.focus = function() {
63277         radios.node().focus();
63278     };
63279
63280
63281     return utilRebind(radio, dispatch$$1, 'on');
63282 }
63283
63284 function uiFieldRestrictions(field, context) {
63285     var dispatch$$1 = dispatch('change'),
63286         breathe = behaviorBreathe(context),
63287         hover = behaviorHover(context),
63288         initialized = false,
63289         vertexID,
63290         fromNodeID;
63291
63292
63293     function restrictions(selection$$1) {
63294         // if form field is hidden or has detached from dom, clean up.
63295         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
63296             selection$$1.call(restrictions.off);
63297             return;
63298         }
63299
63300         var wrap = selection$$1.selectAll('.preset-input-wrap')
63301             .data([0]);
63302
63303         var enter = wrap.enter()
63304             .append('div')
63305             .attr('class', 'preset-input-wrap');
63306
63307         enter
63308             .append('div')
63309             .attr('class', 'restriction-help');
63310
63311
63312         var intersection = osmIntersection(context.graph(), vertexID),
63313             graph = intersection.graph,
63314             vertex = graph.entity(vertexID),
63315             filter = utilFunctor(true),
63316             extent$$1 = geoExtent$$1(),
63317             projection = geoRawMercator();
63318
63319         var d = utilGetDimensions(wrap.merge(enter)),
63320             c = [d[0] / 2, d[1] / 2],
63321             z = 24;
63322
63323         projection
63324             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
63325
63326         var s = projection(vertex.loc);
63327
63328         projection
63329             .translate([c[0] - s[0], c[1] - s[1]])
63330             .clipExtent([[0, 0], d]);
63331
63332         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
63333             drawVertices = svgVertices$$1(projection, context),
63334             drawLines = svgLines$$1(projection, context),
63335             drawTurns = svgTurns(projection, context);
63336
63337         enter
63338             .call(drawLayers);
63339
63340         wrap = wrap
63341             .merge(enter);
63342
63343         var surface = wrap.selectAll('.surface');
63344
63345         if (!enter.empty()) {
63346             initialized = true;
63347             surface
63348                 .call(breathe)
63349                 .call(hover);
63350         }
63351
63352         surface
63353             .call(utilSetDimensions, d)
63354             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
63355             .call(drawLines, graph, intersection.ways, filter)
63356             .call(drawTurns, graph, intersection.turns(fromNodeID));
63357
63358         surface
63359             .on('click.restrictions', click)
63360             .on('mouseover.restrictions', mouseover)
63361             .on('mouseout.restrictions', mouseout);
63362
63363         surface
63364             .selectAll('.selected')
63365             .classed('selected', false);
63366
63367         if (fromNodeID) {
63368             surface
63369                 .selectAll('.' + intersection.highways[fromNodeID].id)
63370                 .classed('selected', true);
63371         }
63372
63373         mouseout();
63374
63375         context.history()
63376             .on('change.restrictions', render);
63377
63378         select(window)
63379             .on('resize.restrictions', function() {
63380                 utilSetDimensions(wrap, null);
63381                 render();
63382             });
63383
63384
63385         function click() {
63386             surface
63387                 .call(breathe.off)
63388                 .call(breathe);
63389
63390             var datum = event.target.__data__;
63391             if (datum instanceof osmEntity$$1) {
63392                 fromNodeID = intersection.adjacentNodeId(datum.id);
63393                 render();
63394             } else if (datum instanceof osmTurn) {
63395                 if (datum.restriction) {
63396                     context.perform(
63397                         actionUnrestrictTurn(datum, projection),
63398                         t('operations.restriction.annotation.delete')
63399                     );
63400                 } else {
63401                     context.perform(
63402                         actionRestrictTurn(datum, projection),
63403                         t('operations.restriction.annotation.create')
63404                     );
63405                 }
63406             }
63407         }
63408
63409
63410         function mouseover() {
63411             var datum = event.target.__data__;
63412             if (datum instanceof osmTurn) {
63413                 var graph = context.graph(),
63414                     presets = context.presets(),
63415                     preset;
63416
63417                 if (datum.restriction) {
63418                     preset = presets.match(graph.entity(datum.restriction), graph);
63419                 } else {
63420                     preset = presets.item('type/restriction/' +
63421                         osmInferRestriction(
63422                             graph,
63423                             datum.from,
63424                             datum.via,
63425                             datum.to,
63426                             projection
63427                         )
63428                     );
63429                 }
63430
63431                 wrap.selectAll('.restriction-help')
63432                     .text(t('operations.restriction.help.' +
63433                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
63434                         { restriction: preset.name() })
63435                     );
63436             }
63437         }
63438
63439
63440         function mouseout() {
63441             wrap.selectAll('.restriction-help')
63442                 .text(t('operations.restriction.help.' +
63443                     (fromNodeID ? 'toggle' : 'select'))
63444                 );
63445         }
63446
63447
63448         function render() {
63449             if (context.hasEntity(vertexID)) {
63450                 restrictions(selection$$1);
63451             }
63452         }
63453     }
63454
63455
63456     restrictions.entity = function(_) {
63457         if (!vertexID || vertexID !== _.id) {
63458             fromNodeID = null;
63459             vertexID = _.id;
63460         }
63461     };
63462
63463
63464     restrictions.tags = function() {};
63465     restrictions.focus = function() {};
63466
63467
63468     restrictions.off = function(selection$$1) {
63469         if (!initialized) return;
63470
63471         selection$$1.selectAll('.surface')
63472             .call(hover.off)
63473             .call(breathe.off)
63474             .on('click.restrictions', null)
63475             .on('mouseover.restrictions', null)
63476             .on('mouseout.restrictions', null);
63477
63478         context.history()
63479             .on('change.restrictions', null);
63480
63481         select(window)
63482             .on('resize.restrictions', null);
63483     };
63484
63485
63486     return utilRebind(restrictions, dispatch$$1, 'on');
63487 }
63488
63489 function uiFieldTextarea(field) {
63490     var dispatch$$1 = dispatch('change'),
63491         input = select(null);
63492
63493
63494     function textarea(selection$$1) {
63495         input = selection$$1.selectAll('textarea')
63496             .data([0]);
63497
63498         input = input.enter()
63499             .append('textarea')
63500             .attr('id', 'preset-input-' + field.id)
63501             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
63502             .attr('maxlength', 255)
63503             .on('input', change(true))
63504             .on('blur', change())
63505             .on('change', change())
63506             .merge(input);
63507     }
63508
63509
63510     function change(onInput) {
63511         return function() {
63512             var t$$1 = {};
63513             t$$1[field.key] = utilGetSetValue(input) || undefined;
63514             dispatch$$1.call('change', this, t$$1, onInput);
63515         };
63516     }
63517
63518
63519     textarea.tags = function(tags) {
63520         utilGetSetValue(input, tags[field.key] || '');
63521     };
63522
63523
63524     textarea.focus = function() {
63525         input.node().focus();
63526     };
63527
63528
63529     return utilRebind(textarea, dispatch$$1, 'on');
63530 }
63531
63532 function uiFieldWikipedia(field, context) {
63533     var dispatch$$1 = dispatch('change'),
63534         wikipedia = services.wikipedia,
63535         wikidata = services.wikidata,
63536         link = select(null),
63537         lang = select(null),
63538         title = select(null),
63539         entity;
63540
63541
63542     function wiki(selection$$1) {
63543         var langcombo = d3combobox()
63544             .fetcher(function(value, cb) {
63545                 var v = value.toLowerCase();
63546
63547                 cb(dataWikipedia.filter(function(d) {
63548                     return d[0].toLowerCase().indexOf(v) >= 0 ||
63549                         d[1].toLowerCase().indexOf(v) >= 0 ||
63550                         d[2].toLowerCase().indexOf(v) >= 0;
63551                 }).map(function(d) {
63552                     return { value: d[1] };
63553                 }));
63554             });
63555
63556         var titlecombo = d3combobox()
63557             .fetcher(function(value, cb) {
63558                 if (!value) {
63559                     value = context.entity(entity.id).tags.name || '';
63560                 }
63561
63562                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
63563                 searchfn(language()[2], value, function(query, data$$1) {
63564                     cb(data$$1.map(function(d) {
63565                         return { value: d };
63566                     }));
63567                 });
63568             });
63569
63570
63571         lang = selection$$1.selectAll('input.wiki-lang')
63572             .data([0]);
63573
63574         lang = lang.enter()
63575             .append('input')
63576             .attr('type', 'text')
63577             .attr('class', 'wiki-lang')
63578             .attr('placeholder', t('translate.localized_translation_language'))
63579             .merge(lang);
63580
63581         utilGetSetValue(lang, language()[1]);
63582
63583         lang
63584             .call(langcombo)
63585             .on('blur', changeLang)
63586             .on('change', changeLang);
63587
63588
63589         title = selection$$1.selectAll('input.wiki-title')
63590             .data([0]);
63591
63592         title = title.enter()
63593             .append('input')
63594             .attr('type', 'text')
63595             .attr('class', 'wiki-title')
63596             .attr('id', 'preset-input-' + field.id)
63597             .merge(title);
63598
63599         title
63600             .call(titlecombo)
63601             .on('blur', blur)
63602             .on('change', change);
63603
63604
63605         link = selection$$1.selectAll('a.wiki-link')
63606             .data([0]);
63607
63608         link = link.enter()
63609             .append('a')
63610             .attr('class', 'wiki-link button-input-action minor')
63611             .attr('tabindex', -1)
63612             .attr('target', '_blank')
63613             .call(svgIcon('#icon-out-link', 'inline'))
63614             .merge(link);
63615     }
63616
63617
63618     function language() {
63619         var value = utilGetSetValue(lang).toLowerCase();
63620         var locale = utilDetect().locale.toLowerCase();
63621         var localeLanguage;
63622         return lodash.find(dataWikipedia, function(d) {
63623             if (d[2] === locale) localeLanguage = d;
63624             return d[0].toLowerCase() === value ||
63625                 d[1].toLowerCase() === value ||
63626                 d[2] === value;
63627         }) || localeLanguage || ['English', 'English', 'en'];
63628     }
63629
63630
63631     function changeLang() {
63632         utilGetSetValue(lang, language()[1]);
63633         change(true);
63634     }
63635
63636
63637     function blur() {
63638         change(true);
63639     }
63640
63641
63642     function change(skipWikidata) {
63643         var value = utilGetSetValue(title),
63644             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
63645             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63646             anchor,
63647             syncTags = {};
63648
63649         if (l) {
63650             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
63651             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
63652             if (m[3]) {
63653                 try {
63654                     // Best-effort `anchordecode:` implementation
63655                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
63656                 } catch (e) {
63657                     anchor = decodeURIComponent(m[3]);
63658                 }
63659                 value += '#' + anchor.replace(/_/g, ' ');
63660             }
63661             value = value.slice(0, 1).toUpperCase() + value.slice(1);
63662             utilGetSetValue(lang, l[1]);
63663             utilGetSetValue(title, value);
63664         }
63665
63666         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
63667         if (!skipWikidata) {
63668             syncTags.wikidata = undefined;
63669         }
63670
63671         dispatch$$1.call('change', this, syncTags);
63672
63673
63674         if (skipWikidata || !value || !language()[2]) return;
63675
63676         // attempt asynchronous update of wikidata tag..
63677         var initEntityId = entity.id,
63678             initWikipedia = context.entity(initEntityId).tags.wikipedia;
63679
63680         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
63681             if (!data$$1 || !Object.keys(data$$1).length) return;
63682             var qids = Object.keys(data$$1);
63683
63684             // 1. most recent change was a tag change
63685             var annotation = t('operations.change_tags.annotation'),
63686                 currAnnotation = context.history().undoAnnotation();
63687             if (currAnnotation !== annotation) return;
63688
63689             // 2. same entity exists and still selected
63690             var selectedIds = context.selectedIDs(),
63691                 currEntityId = selectedIds.length > 0 && selectedIds[0];
63692             if (currEntityId !== initEntityId) return;
63693
63694             // 3. wikipedia value has not changed
63695             var currTags = lodash.clone(context.entity(currEntityId).tags);
63696             if (initWikipedia !== currTags.wikipedia) return;
63697
63698             // ok to coalesce the update of wikidata tag into the previous tag change
63699             currTags.wikidata = qids && lodash.find(qids, function(id) {
63700                 return id.match(/^Q\d+$/);
63701             });
63702
63703             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
63704             dispatch$$1.call('change', this, currTags);
63705         });
63706     }
63707
63708
63709     wiki.tags = function(tags) {
63710         var value = tags[field.key] || '',
63711             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
63712             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
63713             anchor = m && m[3];
63714
63715         // value in correct format
63716         if (l) {
63717             utilGetSetValue(lang, l[1]);
63718             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
63719             if (anchor) {
63720                 try {
63721                     // Best-effort `anchorencode:` implementation
63722                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
63723                 } catch (e) {
63724                     anchor = anchor.replace(/ /g, '_');
63725                 }
63726             }
63727             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
63728                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
63729
63730         // unrecognized value format
63731         } else {
63732             utilGetSetValue(title, value);
63733             if (value && value !== '') {
63734                 utilGetSetValue(lang, '');
63735             }
63736             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
63737         }
63738     };
63739
63740
63741     wiki.entity = function(_) {
63742         if (!arguments.length) return entity;
63743         entity = _;
63744         return wiki;
63745     };
63746
63747
63748     wiki.focus = function() {
63749         title.node().focus();
63750     };
63751
63752
63753     return utilRebind(wiki, dispatch$$1, 'on');
63754 }
63755
63756 var uiFields = {
63757     access: uiFieldAccess,
63758     address: uiFieldAddress,
63759     check: uiFieldCheck,
63760     defaultcheck: uiFieldCheck,
63761     combo: uiFieldCombo,
63762     typeCombo: uiFieldCombo,
63763     multiCombo: uiFieldCombo,
63764     networkCombo: uiFieldCombo,
63765     cycleway: uiFieldCycleway,
63766     text: uiFieldText,
63767     url: uiFieldText,
63768     number: uiFieldText,
63769     email: uiFieldText,
63770     tel: uiFieldText,
63771     localized: uiFieldLocalized,
63772     lanes: uiFieldLanes,
63773     maxspeed: uiFieldMaxspeed,
63774     radio: uiFieldRadio,
63775     restrictions: uiFieldRestrictions,
63776     textarea: uiFieldTextarea,
63777     wikipedia: uiFieldWikipedia
63778 };
63779
63780 function uiPreset(context) {
63781     var dispatch$$1 = dispatch('change'),
63782         state,
63783         fieldsArr,
63784         preset,
63785         tags,
63786         id;
63787
63788
63789     // Field Constructor
63790     function UIField(field, entity, show) {
63791         field = lodash.clone(field);
63792
63793         field.input = uiFields[field.type](field, context)
63794             .on('change', function(t$$1, onInput) {
63795                 dispatch$$1.call('change', field, t$$1, onInput);
63796             });
63797
63798         if (field.input.entity) field.input.entity(entity);
63799
63800         field.keys = field.keys || [field.key];
63801
63802         field.show = show;
63803
63804         field.shown = function() {
63805             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
63806         };
63807
63808         field.modified = function() {
63809             var original = context.graph().base().entities[entity.id];
63810             return lodash.some(field.keys, function(key) {
63811                 return original ? tags[key] !== original.tags[key] : tags[key];
63812             });
63813         };
63814
63815         field.revert = function() {
63816             var original = context.graph().base().entities[entity.id],
63817                 t$$1 = {};
63818             field.keys.forEach(function(key) {
63819                 t$$1[key] = original ? original.tags[key] : undefined;
63820             });
63821             return t$$1;
63822         };
63823
63824         field.present = function() {
63825             return lodash.some(field.keys, function(key) {
63826                 return tags[key];
63827             });
63828         };
63829
63830         field.remove = function() {
63831             var t$$1 = {};
63832             field.keys.forEach(function(key) {
63833                 t$$1[key] = undefined;
63834             });
63835             return t$$1;
63836         };
63837
63838         return field;
63839     }
63840
63841
63842     function fieldKey(field) {
63843         return field.id;
63844     }
63845
63846
63847     function presets(selection$$1) {
63848         selection$$1.call(uiDisclosure()
63849             .title(t('inspector.all_fields'))
63850             .expanded(context.storage('preset_fields.expanded') !== 'false')
63851             .on('toggled', toggled)
63852             .content(content)
63853         );
63854
63855         function toggled(expanded) {
63856             context.storage('preset_fields.expanded', expanded);
63857         }
63858     }
63859
63860
63861     function content(selection$$1) {
63862         if (!fieldsArr) {
63863             var entity = context.entity(id),
63864                 geometry = context.geometry(id),
63865                 presets = context.presets();
63866
63867             fieldsArr = [];
63868
63869             if (presets.field('name')) {
63870                 fieldsArr.push(UIField(presets.field('name'), entity));
63871             }
63872
63873             preset.fields.forEach(function(field) {
63874                 if (field.matchGeometry(geometry)) {
63875                     fieldsArr.push(UIField(field, entity, true));
63876                 }
63877             });
63878
63879             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
63880                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
63881             }
63882
63883             presets.universal().forEach(function(field) {
63884                 if (preset.fields.indexOf(field) < 0) {
63885                     fieldsArr.push(UIField(field, entity));
63886                 }
63887             });
63888         }
63889
63890         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
63891             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
63892
63893
63894         var form = selection$$1.selectAll('.preset-form')
63895             .data([0]);
63896
63897         form = form.enter()
63898             .append('div')
63899             .attr('class', 'preset-form inspector-inner fillL3')
63900             .merge(form);
63901
63902
63903         var fields = form.selectAll('.form-field')
63904             .data(shown, fieldKey);
63905
63906         fields.exit()
63907             .remove();
63908
63909         // Enter
63910         var enter = fields.enter()
63911             .append('div')
63912             .attr('class', function(field) {
63913                 return 'form-field form-field-' + field.id;
63914             });
63915
63916         var label = enter
63917             .append('label')
63918             .attr('class', 'form-label')
63919             .attr('for', function(field) { return 'preset-input-' + field.id; })
63920             .text(function(field) { return field.label(); });
63921
63922         var wrap = label
63923             .append('div')
63924             .attr('class', 'form-label-button-wrap');
63925
63926         wrap.append('button')
63927             .attr('class', 'remove-icon')
63928             .attr('tabindex', -1)
63929             .call(svgIcon('#operation-delete'));
63930
63931         wrap.append('button')
63932             .attr('class', 'modified-icon')
63933             .attr('tabindex', -1)
63934             .call(
63935                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
63936             );
63937
63938
63939         // Update
63940         fields = fields
63941             .merge(enter);
63942
63943         fields.selectAll('.form-label-button-wrap .remove-icon')
63944             .on('click', remove);
63945
63946         fields.selectAll('.modified-icon')
63947             .on('click', revert);
63948
63949         fields
63950             .order()
63951             .classed('modified', function(field) { return field.modified(); })
63952             .classed('present', function(field) { return field.present(); })
63953             .each(function(field) {
63954                 var reference = uiTagReference(field.reference || { key: field.key }, context);
63955
63956                 if (state === 'hover') {
63957                     reference.showing(false);
63958                 }
63959
63960                 select(this)
63961                     .call(field.input)
63962                     .selectAll('input')
63963                     .on('keydown', function() {
63964                         // if user presses enter, and combobox is not active, accept edits..
63965                         if (event.keyCode === 13 && select('.combobox').empty()) {
63966                             context.enter(modeBrowse(context));
63967                         }
63968                     })
63969                     .call(reference.body)
63970                     .select('.form-label-button-wrap')
63971                     .call(reference.button);
63972
63973                 field.input.tags(tags);
63974             });
63975
63976         notShown = notShown.map(function(field) {
63977             return {
63978                 title: field.label(),
63979                 value: field.label(),
63980                 field: field
63981             };
63982         });
63983
63984
63985         var more = selection$$1.selectAll('.more-fields')
63986             .data((notShown.length > 0) ? [0] : []);
63987
63988         more.exit()
63989             .remove();
63990
63991         more = more.enter()
63992             .append('div')
63993             .attr('class', 'more-fields')
63994             .append('label')
63995             .text(t('inspector.add_fields'))
63996             .merge(more);
63997
63998
63999         var input = more.selectAll('.value')
64000             .data([0]);
64001
64002         input.exit()
64003             .remove();
64004
64005         input = input.enter()
64006             .append('input')
64007             .attr('class', 'value')
64008             .attr('type', 'text')
64009             .merge(input);
64010
64011         input
64012             .call(utilGetSetValue, '')
64013             .attr('placeholder', function() {
64014                 var placeholder = [];
64015                 for (var field in notShown) {
64016                     placeholder.push(notShown[field].title);
64017                 }
64018                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
64019             })
64020             .call(d3combobox().data(notShown)
64021                 .minItems(1)
64022                 .on('accept', show));
64023
64024
64025         function show(field) {
64026             field = field.field;
64027             field.show = true;
64028             content(selection$$1);
64029             field.input.focus();
64030         }
64031
64032
64033         function revert(field) {
64034             event.stopPropagation();
64035             event.preventDefault();
64036             dispatch$$1.call('change', field, field.revert());
64037         }
64038
64039
64040         function remove(field) {
64041             event.stopPropagation();
64042             event.preventDefault();
64043             dispatch$$1.call('change', field, field.remove());
64044         }
64045     }
64046
64047
64048     presets.preset = function(_) {
64049         if (!arguments.length) return preset;
64050         if (preset && preset.id === _.id) return presets;
64051         preset = _;
64052         fieldsArr = null;
64053         return presets;
64054     };
64055
64056
64057     presets.state = function(_) {
64058         if (!arguments.length) return state;
64059         state = _;
64060         return presets;
64061     };
64062
64063
64064     presets.tags = function(_) {
64065         if (!arguments.length) return tags;
64066         tags = _;
64067         // Don't reset fieldsArr here.
64068         return presets;
64069     };
64070
64071
64072     presets.entityID = function(_) {
64073         if (!arguments.length) return id;
64074         if (id === _) return presets;
64075         id = _;
64076         fieldsArr = null;
64077         return presets;
64078     };
64079
64080
64081     return utilRebind(presets, dispatch$$1, 'on');
64082 }
64083
64084 function uiEntityEditor(context) {
64085     var dispatch$$1 = dispatch('choose'),
64086         state = 'select',
64087         coalesceChanges = false,
64088         modified = false,
64089         base,
64090         id,
64091         activePreset,
64092         reference;
64093
64094     var presetEditor = uiPreset(context)
64095         .on('change', changeTags);
64096     var rawTagEditor = uiRawTagEditor(context)
64097         .on('change', changeTags);
64098
64099
64100     function entityEditor(selection$$1) {
64101         var entity = context.entity(id),
64102             tags = lodash.clone(entity.tags);
64103
64104         // Header
64105         var header = selection$$1.selectAll('.header')
64106             .data([0]);
64107
64108         // Enter
64109         var enter = header.enter()
64110             .append('div')
64111             .attr('class', 'header fillL cf');
64112
64113         enter
64114             .append('button')
64115             .attr('class', 'fl preset-reset preset-choose')
64116             .call(svgIcon((textDirection === 'rtl') ? '#icon-forward' : '#icon-backward'));
64117
64118         enter
64119             .append('button')
64120             .attr('class', 'fr preset-close')
64121             .on('click', function() { context.enter(modeBrowse(context)); })
64122             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
64123
64124         enter
64125             .append('h3')
64126             .text(t('inspector.edit'));
64127
64128         // Update
64129         header = header
64130             .merge(enter);
64131
64132         header.selectAll('.preset-reset')
64133             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64134
64135
64136         // Body
64137         var body = selection$$1.selectAll('.inspector-body')
64138             .data([0]);
64139
64140         // Enter
64141         enter = body.enter()
64142             .append('div')
64143             .attr('class', 'inspector-body');
64144
64145         enter
64146             .append('div')
64147             .attr('class', 'preset-list-item inspector-inner')
64148             .append('div')
64149             .attr('class', 'preset-list-button-wrap')
64150             .append('button')
64151             .attr('class', 'preset-list-button preset-reset')
64152             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
64153             .append('div')
64154             .attr('class', 'label');
64155
64156         enter
64157             .append('div')
64158             .attr('class', 'inspector-border inspector-preset');
64159
64160         enter
64161             .append('div')
64162             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
64163
64164         enter
64165             .append('div')
64166             .attr('class', 'inspector-border raw-member-editor inspector-inner');
64167
64168         enter
64169             .append('div')
64170             .attr('class', 'raw-membership-editor inspector-inner');
64171
64172         // Update
64173         body = body
64174             .merge(enter);
64175
64176         body.selectAll('.preset-list-button-wrap')
64177             .call(reference.button);
64178
64179         body.selectAll('.preset-list-item')
64180             .call(reference.body);
64181
64182         body.selectAll('.preset-reset')
64183             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
64184
64185         body.select('.preset-list-item button')
64186             .call(uiPresetIcon()
64187                 .geometry(context.geometry(id))
64188                 .preset(activePreset));
64189
64190         body.select('.preset-list-item .label')
64191             .text(activePreset.name());
64192
64193         body.select('.inspector-preset')
64194             .call(presetEditor
64195                 .preset(activePreset)
64196                 .entityID(id)
64197                 .tags(tags)
64198                 .state(state));
64199
64200         body.select('.raw-tag-editor')
64201             .call(rawTagEditor
64202                 .preset(activePreset)
64203                 .entityID(id)
64204                 .tags(tags)
64205                 .state(state));
64206
64207         if (entity.type === 'relation') {
64208             body.select('.raw-member-editor')
64209                 .style('display', 'block')
64210                 .call(uiRawMemberEditor(context)
64211                     .entityID(id));
64212         } else {
64213             body.select('.raw-member-editor')
64214                 .style('display', 'none');
64215         }
64216
64217         body.select('.raw-membership-editor')
64218             .call(uiRawMembershipEditor(context)
64219                 .entityID(id));
64220
64221
64222         context.history()
64223             .on('change.entity-editor', historyChanged);
64224
64225
64226         function historyChanged() {
64227             if (state === 'hide') return;
64228
64229             var entity = context.hasEntity(id),
64230                 graph = context.graph();
64231             if (!entity) return;
64232
64233             entityEditor.preset(context.presets().match(entity, graph));
64234             entityEditor.modified(base !== graph);
64235             entityEditor(selection$$1);
64236         }
64237     }
64238
64239
64240     function clean(o) {
64241
64242         function cleanVal(k, v) {
64243             function keepSpaces(k) {
64244                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
64245                     'operating_times', 'smoking_hours', 'happy_hours'];
64246                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
64247             }
64248
64249             var blacklist = ['description', 'note', 'fixme'];
64250             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
64251
64252             var cleaned = v.split(';')
64253                 .map(function(s) { return s.trim(); })
64254                 .join(keepSpaces(k) ? '; ' : ';');
64255
64256             // The code below is not intended to validate websites and emails.
64257             // It is only intended to prevent obvious copy-paste errors. (#2323)
64258
64259             // clean website- and email-like tags
64260             if (k.indexOf('website') !== -1 ||
64261                 k.indexOf('email') !== -1 ||
64262                 cleaned.indexOf('http') === 0) {
64263                 cleaned = cleaned
64264                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
64265
64266             }
64267
64268             return cleaned;
64269         }
64270
64271         var out = {}, k, v;
64272         for (k in o) {
64273             if (k && (v = o[k]) !== undefined) {
64274                 out[k] = cleanVal(k, v);
64275             }
64276         }
64277         return out;
64278     }
64279
64280
64281     // Tag changes that fire on input can all get coalesced into a single
64282     // history operation when the user leaves the field.  #2342
64283     function changeTags(changed, onInput) {
64284         var entity = context.entity(id),
64285             annotation = t('operations.change_tags.annotation'),
64286             tags = lodash.clone(entity.tags);
64287
64288         lodash.forEach(changed, function(v, k) {
64289             if (v !== undefined || tags.hasOwnProperty(k)) {
64290                 tags[k] = v;
64291             }
64292         });
64293
64294         if (!onInput) {
64295             tags = clean(tags);
64296         }
64297
64298         if (!lodash.isEqual(entity.tags, tags)) {
64299             if (coalesceChanges) {
64300                 context.overwrite(actionChangeTags(id, tags), annotation);
64301             } else {
64302                 context.perform(actionChangeTags(id, tags), annotation);
64303                 coalesceChanges = !!onInput;
64304             }
64305         }
64306     }
64307
64308
64309     entityEditor.modified = function(_) {
64310         if (!arguments.length) return modified;
64311         modified = _;
64312         selectAll('button.preset-close use')
64313             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
64314     };
64315
64316
64317     entityEditor.state = function(_) {
64318         if (!arguments.length) return state;
64319         state = _;
64320         return entityEditor;
64321     };
64322
64323
64324     entityEditor.entityID = function(_) {
64325         if (!arguments.length) return id;
64326         id = _;
64327         base = context.graph();
64328         entityEditor.preset(context.presets().match(context.entity(id), base));
64329         entityEditor.modified(false);
64330         coalesceChanges = false;
64331         return entityEditor;
64332     };
64333
64334
64335     entityEditor.preset = function(_) {
64336         if (!arguments.length) return activePreset;
64337         if (_ !== activePreset) {
64338             activePreset = _;
64339             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
64340                 .showing(false);
64341         }
64342         return entityEditor;
64343     };
64344
64345
64346     return utilRebind(entityEditor, dispatch$$1, 'on');
64347 }
64348
64349 function uiPresetList(context) {
64350     var dispatch$$1 = dispatch('choose'),
64351         id,
64352         currentPreset,
64353         autofocus = false;
64354
64355
64356     function presetList(selection$$1) {
64357         var entity = context.entity(id),
64358             geometry = context.geometry(id);
64359
64360         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
64361         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
64362             geometry = 'point';
64363         }
64364
64365         var presets = context.presets().matchGeometry(geometry);
64366
64367         selection$$1.html('');
64368
64369         var messagewrap = selection$$1
64370             .append('div')
64371             .attr('class', 'header fillL cf');
64372
64373         var message = messagewrap
64374             .append('h3')
64375             .text(t('inspector.choose'));
64376
64377         if (context.entity(id).isUsed(context.graph())) {
64378             messagewrap
64379                 .append('button')
64380                 .attr('class', 'preset-choose')
64381                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
64382                 .call(svgIcon((textDirection === 'rtl') ? '#icon-backward' : '#icon-forward'));
64383         } else {
64384             messagewrap
64385                 .append('button')
64386                 .attr('class', 'close')
64387                 .on('click', function() {
64388                     context.enter(modeBrowse(context));
64389                 })
64390                 .call(svgIcon('#icon-close'));
64391         }
64392
64393         function keydown() {
64394             // hack to let delete shortcut work when search is autofocused
64395             if (search.property('value').length === 0 &&
64396                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
64397                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
64398                 event.preventDefault();
64399                 event.stopPropagation();
64400                 operationDelete([id], context)();
64401             } else if (search.property('value').length === 0 &&
64402                 (event.ctrlKey || event.metaKey) &&
64403                 event.keyCode === d3keybinding.keyCodes.z) {
64404                 event.preventDefault();
64405                 event.stopPropagation();
64406                 context.undo();
64407             } else if (!event.ctrlKey && !event.metaKey) {
64408                 select(this).on('keydown', null);
64409             }
64410         }
64411
64412         function keypress() {
64413             // enter
64414             var value = search.property('value');
64415             if (event.keyCode === 13 && value.length) {
64416                 list.selectAll('.preset-list-item:first-child').datum().choose();
64417             }
64418         }
64419
64420         function inputevent() {
64421             var value = search.property('value');
64422             list.classed('filtered', value.length);
64423             if (value.length) {
64424                 var results = presets.search(value, geometry);
64425                 message.text(t('inspector.results', {
64426                     n: results.collection.length,
64427                     search: value
64428                 }));
64429                 list.call(drawList, results);
64430             } else {
64431                 list.call(drawList, context.presets().defaults(geometry, 36));
64432                 message.text(t('inspector.choose'));
64433             }
64434         }
64435
64436         var searchWrap = selection$$1
64437             .append('div')
64438             .attr('class', 'search-header');
64439
64440         var search = searchWrap
64441             .append('input')
64442             .attr('class', 'preset-search-input')
64443             .attr('placeholder', t('inspector.search'))
64444             .attr('type', 'search')
64445             .on('keydown', keydown)
64446             .on('keypress', keypress)
64447             .on('input', inputevent);
64448
64449         searchWrap
64450             .call(svgIcon('#icon-search', 'pre-text'));
64451
64452         if (autofocus) {
64453             search.node().focus();
64454         }
64455
64456         var listWrap = selection$$1
64457             .append('div')
64458             .attr('class', 'inspector-body');
64459
64460         var list = listWrap
64461             .append('div')
64462             .attr('class', 'preset-list fillL cf')
64463             .call(drawList, context.presets().defaults(geometry, 36));
64464     }
64465
64466
64467     function drawList(list, presets) {
64468         var collection = presets.collection.map(function(preset) {
64469             return preset.members ? CategoryItem(preset) : PresetItem(preset);
64470         });
64471
64472         var items = list.selectAll('.preset-list-item')
64473             .data(collection, function(d) { return d.preset.id; });
64474
64475         items.order();
64476
64477         items.exit()
64478             .remove();
64479
64480         items.enter()
64481             .append('div')
64482             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
64483             .classed('current', function(item) { return item.preset === currentPreset; })
64484             .each(function(item) { select(this).call(item); })
64485             .style('opacity', 0)
64486             .transition()
64487             .style('opacity', 1);
64488     }
64489
64490
64491     function CategoryItem(preset) {
64492         var box, sublist, shown = false;
64493
64494         function item(selection$$1) {
64495             var wrap = selection$$1.append('div')
64496                 .attr('class', 'preset-list-button-wrap category col12');
64497
64498             var button = wrap
64499                 .append('button')
64500                 .attr('class', 'preset-list-button')
64501                 .classed('expanded', false)
64502                 .call(uiPresetIcon()
64503                     .geometry(context.geometry(id))
64504                     .preset(preset))
64505                 .on('click', function() {
64506                     var isExpanded = select(this).classed('expanded');
64507                     var iconName = isExpanded ?
64508                         (textDirection === 'rtl' ? '#icon-backward' : '#icon-forward') : '#icon-down';
64509                     select(this)
64510                         .classed('expanded', !isExpanded);
64511                     select(this).selectAll('div.label svg.icon use')
64512                         .attr('href', iconName);
64513                     item.choose();
64514                 });
64515
64516             var label = button
64517                 .append('div')
64518                 .attr('class', 'label');
64519
64520             label
64521                 .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'))
64522                 .append('span')
64523                 .html(function() { return preset.name() + '&hellip;'; });
64524
64525             box = selection$$1.append('div')
64526                 .attr('class', 'subgrid col12')
64527                 .style('max-height', '0px')
64528                 .style('opacity', 0);
64529
64530             box.append('div')
64531                 .attr('class', 'arrow');
64532
64533             sublist = box.append('div')
64534                 .attr('class', 'preset-list fillL3 cf fl');
64535         }
64536
64537
64538         item.choose = function() {
64539             if (!box || !sublist) return;
64540
64541             if (shown) {
64542                 shown = false;
64543                 box.transition()
64544                     .duration(200)
64545                     .style('opacity', '0')
64546                     .style('max-height', '0px')
64547                     .style('padding-bottom', '0px');
64548             } else {
64549                 shown = true;
64550                 sublist.call(drawList, preset.members);
64551                 box.transition()
64552                     .duration(200)
64553                     .style('opacity', '1')
64554                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
64555                     .style('padding-bottom', '20px');
64556             }
64557         };
64558
64559         item.preset = preset;
64560
64561         return item;
64562     }
64563
64564
64565     function PresetItem(preset) {
64566         function item(selection$$1) {
64567             var wrap = selection$$1.append('div')
64568                 .attr('class', 'preset-list-button-wrap col12');
64569
64570             wrap.append('button')
64571                 .attr('class', 'preset-list-button')
64572                 .call(uiPresetIcon()
64573                     .geometry(context.geometry(id))
64574                     .preset(preset))
64575                 .on('click', item.choose)
64576                 .append('div')
64577                 .attr('class', 'label')
64578                 .text(preset.name());
64579
64580             wrap.call(item.reference.button);
64581             selection$$1.call(item.reference.body);
64582         }
64583
64584         item.choose = function() {
64585             context.presets().choose(preset);
64586
64587             context.perform(
64588                 actionChangePreset(id, currentPreset, preset),
64589                 t('operations.change_tags.annotation')
64590             );
64591
64592             dispatch$$1.call('choose', this, preset);
64593         };
64594
64595         item.help = function() {
64596             event.stopPropagation();
64597             item.reference.toggle();
64598         };
64599
64600         item.preset = preset;
64601         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
64602
64603         return item;
64604     }
64605
64606
64607     presetList.autofocus = function(_) {
64608         if (!arguments.length) return autofocus;
64609         autofocus = _;
64610         return presetList;
64611     };
64612
64613
64614     presetList.entityID = function(_) {
64615         if (!arguments.length) return id;
64616         id = _;
64617         presetList.preset(context.presets().match(context.entity(id), context.graph()));
64618         return presetList;
64619     };
64620
64621
64622     presetList.preset = function(_) {
64623         if (!arguments.length) return currentPreset;
64624         currentPreset = _;
64625         return presetList;
64626     };
64627
64628
64629     return utilRebind(presetList, dispatch$$1, 'on');
64630 }
64631
64632 function uiViewOnOSM(context) {
64633     var id;
64634
64635     function viewOnOSM(selection) {
64636         var entity = context.entity(id);
64637
64638         selection.style('display', entity.isNew() ? 'none' : null);
64639
64640         var link = selection.selectAll('.view-on-osm')
64641             .data([0]);
64642
64643         var enter = link.enter()
64644             .append('a')
64645             .attr('class', 'view-on-osm')
64646             .attr('target', '_blank')
64647             .call(svgIcon('#icon-out-link', 'inline'));
64648
64649         enter
64650             .append('span')
64651             .text(t('inspector.view_on_osm'));
64652
64653         link
64654             .merge(enter)
64655             .attr('href', context.connection().entityURL(entity));
64656     }
64657
64658
64659     viewOnOSM.entityID = function(_) {
64660         if (!arguments.length) return id;
64661         id = _;
64662         return viewOnOSM;
64663     };
64664
64665     return viewOnOSM;
64666 }
64667
64668 function uiInspector(context) {
64669     var presetList = uiPresetList(context),
64670         entityEditor = uiEntityEditor(context),
64671         state = 'select',
64672         entityID,
64673         newFeature = false;
64674
64675
64676     function inspector(selection$$1) {
64677         presetList
64678             .entityID(entityID)
64679             .autofocus(newFeature)
64680             .on('choose', setPreset);
64681
64682         entityEditor
64683             .state(state)
64684             .entityID(entityID)
64685             .on('choose', showList);
64686
64687         var wrap = selection$$1.selectAll('.panewrap')
64688             .data([0]);
64689
64690         var enter = wrap.enter()
64691             .append('div')
64692             .attr('class', 'panewrap');
64693
64694         enter
64695             .append('div')
64696             .attr('class', 'preset-list-pane pane');
64697
64698         enter
64699             .append('div')
64700             .attr('class', 'entity-editor-pane pane');
64701
64702         wrap = wrap.merge(enter);
64703         var presetPane = wrap.selectAll('.preset-list-pane');
64704         var editorPane = wrap.selectAll('.entity-editor-pane');
64705
64706         var graph = context.graph(),
64707             entity = context.entity(entityID),
64708             showEditor = state === 'hover' ||
64709                 entity.isUsed(graph) ||
64710                 entity.isHighwayIntersection(graph);
64711
64712         if (showEditor) {
64713             wrap.style('right', '0%');
64714             editorPane.call(entityEditor);
64715         } else {
64716             wrap.style('right', '-100%');
64717             presetPane.call(presetList);
64718         }
64719
64720         var footer = selection$$1.selectAll('.footer')
64721             .data([0]);
64722
64723         footer = footer.enter()
64724             .append('div')
64725             .attr('class', 'footer')
64726             .merge(footer);
64727
64728         footer
64729             .call(uiViewOnOSM(context).entityID(entityID));
64730
64731
64732         function showList(preset) {
64733             wrap.transition()
64734                 .styleTween('right', function() { return value$1('0%', '-100%'); });
64735
64736             presetPane
64737                 .call(presetList.preset(preset).autofocus(true));
64738         }
64739
64740
64741         function setPreset(preset) {
64742             wrap.transition()
64743                 .styleTween('right', function() { return value$1('-100%', '0%'); });
64744
64745             editorPane
64746                 .call(entityEditor.preset(preset));
64747         }
64748     }
64749
64750
64751     inspector.state = function(_) {
64752         if (!arguments.length) return state;
64753         state = _;
64754         entityEditor.state(state);
64755         return inspector;
64756     };
64757
64758
64759     inspector.entityID = function(_) {
64760         if (!arguments.length) return entityID;
64761         entityID = _;
64762         return inspector;
64763     };
64764
64765
64766     inspector.newFeature = function(_) {
64767         if (!arguments.length) return newFeature;
64768         newFeature = _;
64769         return inspector;
64770     };
64771
64772
64773     return inspector;
64774 }
64775
64776 function uiNotice(context) {
64777
64778     return function(selection) {
64779         var div = selection
64780             .append('div')
64781             .attr('class', 'notice');
64782
64783         var button = div
64784             .append('button')
64785             .attr('class', 'zoom-to notice')
64786             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
64787
64788         button
64789             .call(svgIcon('#icon-plus', 'pre-text'))
64790             .append('span')
64791             .attr('class', 'label')
64792             .text(t('zoom_in_edit'));
64793
64794
64795         function disableTooHigh() {
64796             div.style('display', context.editable() ? 'none' : 'block');
64797         }
64798
64799         context.map()
64800             .on('move.notice', lodash.debounce(disableTooHigh, 500));
64801
64802         disableTooHigh();
64803     };
64804 }
64805
64806 function uiSidebar(context) {
64807     var inspector = uiInspector(context),
64808         current;
64809
64810
64811     function sidebar(selection) {
64812         var featureListWrap = selection
64813             .append('div')
64814             .attr('class', 'feature-list-pane')
64815             .call(uiFeatureList(context));
64816
64817         selection
64818             .call(uiNotice(context));
64819
64820         var inspectorWrap = selection
64821             .append('div')
64822             .attr('class', 'inspector-hidden inspector-wrap fr');
64823
64824
64825         function hover(id) {
64826             if (!current && context.hasEntity(id)) {
64827                 featureListWrap
64828                     .classed('inspector-hidden', true);
64829
64830                 inspectorWrap
64831                     .classed('inspector-hidden', false)
64832                     .classed('inspector-hover', true);
64833
64834                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
64835                     inspector
64836                         .state('hover')
64837                         .entityID(id);
64838
64839                     inspectorWrap
64840                         .call(inspector);
64841                 }
64842
64843             } else if (!current) {
64844                 featureListWrap
64845                     .classed('inspector-hidden', false);
64846                 inspectorWrap
64847                     .classed('inspector-hidden', true);
64848                 inspector
64849                     .state('hide');
64850             }
64851         }
64852
64853
64854         sidebar.hover = lodash.throttle(hover, 200);
64855
64856
64857         sidebar.select = function(id, newFeature) {
64858             if (!current && id) {
64859                 featureListWrap
64860                     .classed('inspector-hidden', true);
64861
64862                 inspectorWrap
64863                     .classed('inspector-hidden', false)
64864                     .classed('inspector-hover', false);
64865
64866                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
64867                     inspector
64868                         .state('select')
64869                         .entityID(id)
64870                         .newFeature(newFeature);
64871
64872                     inspectorWrap
64873                         .call(inspector);
64874                 }
64875
64876             } else if (!current) {
64877                 featureListWrap
64878                     .classed('inspector-hidden', false);
64879                 inspectorWrap
64880                     .classed('inspector-hidden', true);
64881                 inspector
64882                     .state('hide');
64883             }
64884         };
64885
64886
64887         sidebar.show = function(component) {
64888             featureListWrap
64889                 .classed('inspector-hidden', true);
64890             inspectorWrap
64891                 .classed('inspector-hidden', true);
64892
64893             if (current) current.remove();
64894             current = selection
64895                 .append('div')
64896                 .attr('class', 'sidebar-component')
64897                 .call(component);
64898         };
64899
64900
64901         sidebar.hide = function() {
64902             featureListWrap
64903                 .classed('inspector-hidden', false);
64904             inspectorWrap
64905                 .classed('inspector-hidden', true);
64906
64907             if (current) current.remove();
64908             current = null;
64909         };
64910     }
64911
64912
64913     sidebar.hover = function() {};
64914     sidebar.hover.cancel = function() {};
64915     sidebar.select = function() {};
64916     sidebar.show = function() {};
64917     sidebar.hide = function() {};
64918
64919     return sidebar;
64920 }
64921
64922 function uiSpinner(context) {
64923     var connection = context.connection();
64924
64925
64926     return function(selection) {
64927         var img = selection
64928             .append('img')
64929             .attr('src', context.imagePath('loader-black.gif'))
64930             .style('opacity', 0);
64931
64932         connection
64933             .on('loading.spinner', function() {
64934                 img.transition()
64935                     .style('opacity', 1);
64936             });
64937
64938         connection
64939             .on('loaded.spinner', function() {
64940                 img.transition()
64941                     .style('opacity', 0);
64942             });
64943     };
64944 }
64945
64946 function uiSplash(context) {
64947
64948     return function(selection$$1) {
64949         if (context.storage('sawSplash'))
64950              return;
64951
64952         context.storage('sawSplash', true);
64953
64954         var modalSelection = uiModal(selection$$1);
64955
64956         modalSelection.select('.modal')
64957             .attr('class', 'modal-splash modal col6');
64958
64959         var introModal = modalSelection.select('.content')
64960             .append('div')
64961             .attr('class', 'fillL');
64962
64963         introModal
64964             .append('div')
64965             .attr('class','modal-section cf')
64966             .append('h3').text(t('splash.welcome'));
64967
64968         introModal
64969             .append('div')
64970             .attr('class','modal-section')
64971             .append('p')
64972             .html(t('splash.text', {
64973                 version: context.version,
64974                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
64975                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
64976             }));
64977
64978         var buttons = introModal
64979             .append('div')
64980             .attr('class', 'modal-actions cf');
64981
64982         buttons
64983             .append('button')
64984             .attr('class', 'col6 walkthrough')
64985             .text(t('splash.walkthrough'))
64986             .on('click', function() {
64987                 select(document.body).call(uiIntro(context));
64988                 modalSelection.close();
64989             });
64990
64991         buttons
64992             .append('button')
64993             .attr('class', 'col6 start')
64994             .text(t('splash.start'))
64995             .on('click', modalSelection.close);
64996
64997         modalSelection.select('button.close')
64998             .attr('class','hide');
64999
65000     };
65001 }
65002
65003 function uiStatus(context) {
65004     var connection = context.connection();
65005
65006     return function(selection$$1) {
65007
65008         function update() {
65009             connection.status(function(err, apiStatus) {
65010                 selection$$1.html('');
65011
65012                 if (err) {
65013                     if (apiStatus === 'rateLimited') {
65014                         selection$$1
65015                             .text(t('status.rateLimit'))
65016                             .append('a')
65017                             .attr('class', 'api-status-login')
65018                             .attr('target', '_blank')
65019                             .call(svgIcon('#icon-out-link', 'inline'))
65020                             .append('span')
65021                             .text(t('login'))
65022                             .on('click.login', function() {
65023                                 event.preventDefault();
65024                                 connection.authenticate();
65025                             });
65026                     } else {
65027                         // TODO: nice messages for different error types
65028                         selection$$1.text(t('status.error'));
65029                     }
65030
65031                 } else if (apiStatus === 'readonly') {
65032                     selection$$1.text(t('status.readonly'));
65033                 } else if (apiStatus === 'offline') {
65034                     selection$$1.text(t('status.offline'));
65035                 }
65036
65037                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
65038             });
65039         }
65040
65041         connection
65042             .on('change', function() { update(selection$$1); });
65043
65044         window.setInterval(update, 90000);
65045         update(selection$$1);
65046     };
65047 }
65048
65049 function uiUndoRedo(context) {
65050     var commands = [{
65051         id: 'undo',
65052         cmd: uiCmd('⌘Z'),
65053         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
65054         annotation: function() { return context.history().undoAnnotation(); }
65055     }, {
65056         id: 'redo',
65057         cmd: uiCmd('⌘⇧Z'),
65058         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
65059         annotation: function() { return context.history().redoAnnotation(); }
65060     }];
65061
65062
65063     function saving() {
65064         return context.mode().id === 'save';
65065     }
65066
65067
65068     return function(selection$$1) {
65069         var tooltipBehavior = tooltip()
65070             .placement('bottom')
65071             .html(true)
65072             .title(function (d) {
65073                 return uiTooltipHtml(d.annotation() ?
65074                     t(d.id + '.tooltip', {action: d.annotation()}) :
65075                     t(d.id + '.nothing'), d.cmd);
65076             });
65077
65078         var buttons = selection$$1.selectAll('button')
65079             .data(commands)
65080             .enter()
65081             .append('button')
65082             .attr('class', 'col6 disabled')
65083             .on('click', function(d) { return d.action(); })
65084             .call(tooltipBehavior);
65085
65086         buttons.each(function(d) {
65087             var iconName = d.id;
65088             if (textDirection === 'rtl') {
65089                 if (iconName === 'undo') {
65090                     iconName = 'redo';
65091                 } else if (iconName === 'redo') {
65092                     iconName = 'undo';
65093                 }
65094             }
65095             select(this)
65096                 .call(svgIcon('#icon-' + iconName));
65097         });
65098
65099         var keybinding = d3keybinding('undo')
65100             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
65101             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
65102
65103         select(document)
65104             .call(keybinding);
65105
65106         context.history()
65107             .on('change.undo_redo', update);
65108
65109         context
65110             .on('enter.undo_redo', update);
65111
65112         function update() {
65113             buttons
65114                 .property('disabled', saving())
65115                 .classed('disabled', function(d) { return !d.annotation(); })
65116                 .each(function() {
65117                     var selection$$1 = select(this);
65118                     if (selection$$1.property('tooltipVisible')) {
65119                         selection$$1.call(tooltipBehavior.show);
65120                     }
65121                 });
65122         }
65123     };
65124 }
65125
65126 function uiZoom(context) {
65127     var zooms = [{
65128         id: 'zoom-in',
65129         icon: 'plus',
65130         title: t('zoom.in'),
65131         action: context.zoomIn,
65132         key: '+'
65133     }, {
65134         id: 'zoom-out',
65135         icon: 'minus',
65136         title: t('zoom.out'),
65137         action: context.zoomOut,
65138         key: '-'
65139     }];
65140
65141
65142     function zoomIn() {
65143         event.preventDefault();
65144         if (!context.inIntro()) context.zoomIn();
65145     }
65146
65147
65148     function zoomOut() {
65149         event.preventDefault();
65150         if (!context.inIntro()) context.zoomOut();
65151     }
65152
65153
65154     function zoomInFurther() {
65155         event.preventDefault();
65156         if (!context.inIntro()) context.zoomInFurther();
65157     }
65158
65159
65160     function zoomOutFurther() {
65161         event.preventDefault();
65162         if (!context.inIntro()) context.zoomOutFurther();
65163     }
65164
65165
65166     return function(selection$$1) {
65167         var button = selection$$1.selectAll('button')
65168             .data(zooms)
65169             .enter()
65170             .append('button')
65171             .attr('tabindex', -1)
65172             .attr('class', function(d) { return d.id; })
65173             .on('click.editor', function(d) { d.action(); })
65174             .call(tooltip()
65175                 .placement((textDirection === 'rtl') ? 'right' : 'left')
65176                 .html(true)
65177                 .title(function(d) {
65178                     return uiTooltipHtml(d.title, d.key);
65179                 })
65180             );
65181
65182         button.each(function(d) {
65183             select(this)
65184                 .call(svgIcon('#icon-' + d.icon, 'light'));
65185         });
65186
65187         var keybinding = d3keybinding('zoom');
65188
65189         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
65190             keybinding.on([key, '⇧' + key], zoomIn);
65191             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
65192         });
65193         lodash.each(['-','ffminus','dash'], function(key) {
65194             keybinding.on([key, '⇧' + key], zoomOut);
65195             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
65196         });
65197
65198         select(document)
65199             .call(keybinding);
65200     };
65201 }
65202
65203 function uiInit(context) {
65204     var uiInitCounter = 0;
65205
65206
65207     function render(container) {
65208         container
65209             .attr('dir', textDirection);
65210
65211         var map$$1 = context.map();
65212
65213         var hash = behaviorHash(context);
65214         hash();
65215
65216         if (!hash.hadHash) {
65217             map$$1.centerZoom([0, 0], 2);
65218         }
65219
65220         container
65221             .append('svg')
65222             .attr('id', 'defs')
65223             .call(svgDefs(context));
65224
65225         container
65226             .append('div')
65227             .attr('id', 'sidebar')
65228             .attr('class', 'col4')
65229             .call(ui.sidebar);
65230
65231         var content = container
65232             .append('div')
65233             .attr('id', 'content')
65234             .attr('class', 'active');
65235
65236         var bar = content
65237             .append('div')
65238             .attr('id', 'bar')
65239             .attr('class', 'fillD');
65240
65241         content
65242             .append('div')
65243             .attr('id', 'map')
65244             .attr('dir', 'ltr')
65245             .call(map$$1);
65246
65247         content
65248             .call(uiMapInMap(context));
65249
65250         content
65251             .append('div')
65252             .call(uiInfo(context));
65253
65254         bar
65255             .append('div')
65256             .attr('class', 'spacer col4');
65257
65258         var limiter = bar.append('div')
65259             .attr('class', 'limiter');
65260
65261         limiter
65262             .append('div')
65263             .attr('class', 'button-wrap joined col3')
65264             .call(uiModes(context), limiter);
65265
65266         limiter
65267             .append('div')
65268             .attr('class', 'button-wrap joined col1')
65269             .call(uiUndoRedo(context));
65270
65271         limiter
65272             .append('div')
65273             .attr('class', 'button-wrap col1')
65274             .call(uiSave(context));
65275
65276         bar
65277             .append('div')
65278             .attr('class', 'full-screen')
65279             .call(uiFullScreen(context));
65280
65281         bar
65282             .append('div')
65283             .attr('class', 'spinner')
65284             .call(uiSpinner(context));
65285
65286         var controls = bar
65287             .append('div')
65288             .attr('class', 'map-controls');
65289
65290         controls
65291             .append('div')
65292             .attr('class', 'map-control zoombuttons')
65293             .call(uiZoom(context));
65294
65295         controls
65296             .append('div')
65297             .attr('class', 'map-control geolocate-control')
65298             .call(uiGeolocate(context));
65299
65300         controls
65301             .append('div')
65302             .attr('class', 'map-control background-control')
65303             .call(uiBackground(context));
65304
65305         controls
65306             .append('div')
65307             .attr('class', 'map-control map-data-control')
65308             .call(uiMapData(context));
65309
65310         controls
65311             .append('div')
65312             .attr('class', 'map-control help-control')
65313             .call(uiHelp(context));
65314
65315         var about = content
65316             .append('div')
65317             .attr('id', 'about');
65318
65319         about
65320             .append('div')
65321             .attr('id', 'attrib')
65322             .attr('dir', 'ltr')
65323             .call(uiAttribution(context));
65324
65325         var footer = about
65326             .append('div')
65327             .attr('id', 'footer')
65328             .attr('class', 'fillD');
65329
65330         footer
65331             .append('div')
65332             .attr('class', 'api-status')
65333             .call(uiStatus(context));
65334
65335         footer
65336             .append('div')
65337             .attr('id', 'scale-block')
65338             .call(uiScale(context));
65339
65340         var aboutList = footer
65341             .append('div')
65342             .attr('id', 'info-block')
65343             .append('ul')
65344             .attr('id', 'about-list');
65345
65346         if (!context.embed()) {
65347             aboutList.call(uiAccount(context));
65348         }
65349
65350         aboutList
65351             .append('li')
65352             .append('a')
65353             .attr('target', '_blank')
65354             .attr('tabindex', -1)
65355             .attr('href', 'https://github.com/openstreetmap/iD')
65356             .text(context.version);
65357
65358         var issueLinks = aboutList
65359             .append('li');
65360
65361         issueLinks
65362             .append('a')
65363             .attr('target', '_blank')
65364             .attr('tabindex', -1)
65365             .attr('href', 'https://github.com/openstreetmap/iD/issues')
65366             .call(svgIcon('#icon-bug', 'light'))
65367             .call(tooltip().title(t('report_a_bug')).placement('top'));
65368
65369         issueLinks
65370             .append('a')
65371             .attr('target', '_blank')
65372             .attr('tabindex', -1)
65373             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
65374             .call(svgIcon('#icon-translate', 'light'))
65375             .call(tooltip().title(t('help_translate')).placement('top'));
65376
65377         aboutList
65378             .append('li')
65379             .attr('class', 'feature-warning')
65380             .attr('tabindex', -1)
65381             .call(uiFeatureInfo(context));
65382
65383         aboutList
65384             .append('li')
65385             .attr('class', 'user-list')
65386             .attr('tabindex', -1)
65387             .call(uiContributors(context));
65388
65389
65390         window.onbeforeunload = function() {
65391             return context.save();
65392         };
65393
65394         window.onunload = function() {
65395             context.history().unlock();
65396         };
65397
65398         var mapDimensions = map$$1.dimensions();
65399
65400
65401         function onResize() {
65402             mapDimensions = utilGetDimensions(content, true);
65403             map$$1.dimensions(mapDimensions);
65404         }
65405
65406         select(window)
65407             .on('resize.editor', onResize);
65408
65409         onResize();
65410
65411         function pan(d) {
65412             return function() {
65413                 event.preventDefault();
65414                 if (!context.inIntro()) {
65415                     context.pan(d, 100);
65416                 }
65417             };
65418         }
65419
65420
65421         // pan amount
65422         var pa = 10;
65423
65424         var keybinding = d3keybinding('main')
65425             .on('⌫', function() { event.preventDefault(); })
65426             .on('←', pan([pa, 0]))
65427             .on('↑', pan([0, pa]))
65428             .on('→', pan([-pa, 0]))
65429             .on('↓', pan([0, -pa]))
65430             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
65431             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
65432             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
65433             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
65434
65435         select(document)
65436             .call(keybinding);
65437
65438         context.enter(modeBrowse(context));
65439
65440         if (!uiInitCounter++) {
65441             context.container()
65442                 .call(uiSplash(context))
65443                 .call(uiRestore(context));
65444         }
65445
65446         var authenticating = uiLoading(context)
65447             .message(t('loading_auth'))
65448             .blocking(true);
65449
65450         context.connection()
65451             .on('authLoading.ui', function() {
65452                 context.container()
65453                     .call(authenticating);
65454             })
65455             .on('authDone.ui', function() {
65456                 authenticating.close();
65457             });
65458
65459         uiInitCounter++;
65460     }
65461
65462
65463     var renderCallback;
65464
65465     function ui(node, callback) {
65466         renderCallback = callback;
65467         var container = select(node);
65468         context.container(container);
65469         context.loadLocale(function(err) {
65470             if (!err) {
65471                 render(container);
65472             }
65473             if (callback) {
65474                 callback(err);
65475             }
65476         });
65477     }
65478
65479
65480     ui.restart = function(arg) {
65481         context.locale(arg);
65482         context.loadLocale(function(err) {
65483             if (!err) {
65484                 context.container().selectAll('*').remove();
65485                 render(context.container());
65486                 if (renderCallback) renderCallback();
65487             }
65488         });
65489     };
65490
65491
65492     ui.sidebar = uiSidebar(context);
65493
65494     return ui;
65495 }
65496
65497 function uiCommit(context) {
65498     var dispatch$$1 = dispatch('cancel', 'save');
65499
65500
65501     function commit(selection$$1) {
65502         var changes = context.history().changes(),
65503             summary = context.history().difference().summary();
65504
65505         selection$$1
65506             .append('div')
65507             .attr('class', 'header fillL')
65508             .append('h3')
65509             .text(t('commit.title'));
65510
65511         var body = selection$$1
65512             .append('div')
65513             .attr('class', 'body');
65514
65515         var commentSection = body
65516             .append('div')
65517             .attr('class', 'modal-section form-field commit-form');
65518
65519         commentSection
65520             .append('label')
65521             .attr('class', 'form-label')
65522             .text(t('commit.message_label'));
65523
65524         var commentField = commentSection
65525             .append('textarea')
65526             .attr('placeholder', t('commit.description_placeholder'))
65527             .attr('maxlength', 255)
65528             .property('value', context.storage('comment') || '')
65529             .on('input.save', checkComment)
65530             .on('change.save', checkComment)
65531             .on('blur.save', function() {
65532                 context.storage('comment', this.value);
65533             });
65534
65535
65536         commentField.node().select();
65537
65538         context.connection().userChangesets(function (err, changesets) {
65539             if (err) return;
65540
65541             var comments = changesets.map(function(changeset) {
65542                 return {
65543                     title: changeset.tags.comment,
65544                     value: changeset.tags.comment
65545                 };
65546             });
65547
65548             commentField
65549                 .call(d3combobox()
65550                     .caseSensitive(true)
65551                     .data(lodash.uniqBy(comments, 'title'))
65552                 );
65553         });
65554
65555         var clippyArea = commentSection.append('div')
65556             .attr('class', 'clippy-area');
65557
65558         var changeSetInfo = commentSection.append('div')
65559             .attr('class', 'changeset-info');
65560
65561         changeSetInfo.append('a')
65562             .attr('target', '_blank')
65563             .attr('tabindex', -1)
65564             .call(svgIcon('#icon-out-link', 'inline'))
65565             .attr('href', t('commit.about_changeset_comments_link'))
65566             .append('span')
65567             .text(t('commit.about_changeset_comments'));
65568
65569
65570         // Warnings
65571         var warnings = body.selectAll('div.warning-section')
65572             .data([context.history().validate(changes)]);
65573
65574         warnings = warnings.enter()
65575             .append('div')
65576             .attr('class', 'modal-section warning-section fillL2')
65577             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
65578             .style('background', '#ffb')
65579             .merge(warnings);
65580
65581         warnings
65582             .append('h3')
65583             .text(t('commit.warnings'));
65584
65585         warnings
65586             .append('ul')
65587             .attr('class', 'changeset-list');
65588
65589         var warningLi = warnings.select('ul').selectAll('li')
65590             .data(function(d) { return d; });
65591
65592         warningLi = warningLi.enter()
65593             .append('li')
65594             .on('mouseover', mouseover)
65595             .on('mouseout', mouseout)
65596             .on('click', warningClick)
65597             .merge(warningLi);
65598
65599         warningLi
65600             .call(svgIcon('#icon-alert', 'pre-text'));
65601
65602         warningLi
65603             .append('strong')
65604             .text(function(d) { return d.message; });
65605
65606         warningLi.filter(function(d) { return d.tooltip; })
65607             .call(tooltip()
65608                 .title(function(d) { return d.tooltip; })
65609                 .placement('top')
65610             );
65611
65612
65613         // Upload Explanation
65614         var saveSection = body
65615             .append('div')
65616             .attr('class','modal-section save-section fillL cf');
65617
65618         var prose = saveSection
65619             .append('p')
65620             .attr('class', 'commit-info')
65621             .html(t('commit.upload_explanation'));
65622
65623
65624         context.connection().userDetails(function(err, user) {
65625             if (err) return;
65626
65627             var userLink = select(document.createElement('div'));
65628
65629             if (user.image_url) {
65630                 userLink
65631                     .append('img')
65632                     .attr('src', user.image_url)
65633                     .attr('class', 'icon pre-text user-icon');
65634             }
65635
65636             userLink
65637                 .append('a')
65638                 .attr('class','user-info')
65639                 .text(user.display_name)
65640                 .attr('href', context.connection().userURL(user.display_name))
65641                 .attr('tabindex', -1)
65642                 .attr('target', '_blank');
65643
65644             prose
65645                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
65646         });
65647
65648
65649         // Buttons
65650         var buttonSection = saveSection
65651             .append('div')
65652             .attr('class','buttons fillL cf');
65653
65654         var cancelButton = buttonSection
65655             .append('button')
65656             .attr('class', 'secondary-action col5 button cancel-button')
65657             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65658
65659         cancelButton
65660             .append('span')
65661             .attr('class', 'label')
65662             .text(t('commit.cancel'));
65663
65664         var saveButton = buttonSection
65665             .append('button')
65666             .attr('class', 'action col5 button save-button')
65667             .attr('disabled', function() {
65668                 var n = select('.commit-form textarea').node();
65669                 return (n && n.value.length) ? null : true;
65670             })
65671             .on('click.save', function() {
65672                 dispatch$$1.call('save', this, {
65673                     comment: commentField.node().value
65674                 });
65675             });
65676
65677         saveButton
65678             .append('span')
65679             .attr('class', 'label')
65680             .text(t('commit.save'));
65681
65682
65683         // Changes
65684         var changeSection = body
65685             .append('div')
65686             .attr('class', 'commit-section modal-section fillL2');
65687
65688         changeSection.append('h3')
65689             .text(t('commit.changes', { count: summary.length }));
65690
65691         var li = changeSection
65692             .append('ul')
65693             .attr('class', 'changeset-list')
65694             .selectAll('li')
65695             .data(summary);
65696
65697         li = li.enter()
65698             .append('li')
65699             .on('mouseover', mouseover)
65700             .on('mouseout', mouseout)
65701             .on('click', zoomToEntity)
65702             .merge(li);
65703
65704         li.each(function(d) {
65705             select(this)
65706                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
65707         });
65708
65709         li.append('span')
65710             .attr('class', 'change-type')
65711             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
65712
65713         li.append('strong')
65714             .attr('class', 'entity-type')
65715             .text(function(d) {
65716                 var matched = context.presets().match(d.entity, d.graph);
65717                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
65718             });
65719
65720         li.append('span')
65721             .attr('class', 'entity-name')
65722             .text(function(d) {
65723                 var name = utilDisplayName(d.entity) || '',
65724                     string = '';
65725                 if (name !== '') string += ':';
65726                 return string += ' ' + name;
65727             });
65728
65729         li.style('opacity', 0)
65730             .transition()
65731             .style('opacity', 1);
65732
65733
65734         // Call checkComment off the bat, in case a changeset
65735         // comment is recovered from localStorage
65736         utilTriggerEvent(commentField, 'input');
65737
65738
65739         function mouseover(d) {
65740             if (d.entity) {
65741                 context.surface().selectAll(
65742                     utilEntityOrMemberSelector([d.entity.id], context.graph())
65743                 ).classed('hover', true);
65744             }
65745         }
65746
65747
65748         function mouseout() {
65749             context.surface().selectAll('.hover')
65750                 .classed('hover', false);
65751         }
65752
65753
65754         function warningClick(d) {
65755             if (d.entity) {
65756                 context.map().zoomTo(d.entity);
65757                 context.enter(
65758                     modeSelect(context, [d.entity.id]).suppressMenu(true)
65759                 );
65760             }
65761         }
65762
65763
65764         function zoomToEntity(change) {
65765             var entity = change.entity;
65766             if (change.changeType !== 'deleted' &&
65767                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
65768                 context.map().zoomTo(entity);
65769                 context.surface().selectAll(
65770                     utilEntityOrMemberSelector([entity.id], context.graph()))
65771                     .classed('hover', true);
65772             }
65773         }
65774
65775
65776         function checkComment() {
65777             selectAll('.save-section .save-button')
65778                 .attr('disabled', (this.value.length ? null : true));
65779
65780             var googleWarning = clippyArea
65781                .html('')
65782                .selectAll('a')
65783                .data(this.value.match(/google/i) ? [true] : []);
65784
65785             googleWarning.exit()
65786                 .remove();
65787
65788             googleWarning.enter()
65789                .append('a')
65790                .attr('target', '_blank')
65791                .attr('tabindex', -1)
65792                .call(svgIcon('#icon-alert', 'inline'))
65793                .attr('href', t('commit.google_warning_link'))
65794                .append('span')
65795                .text(t('commit.google_warning'));
65796         }
65797     }
65798
65799     return utilRebind(commit, dispatch$$1, 'on');
65800 }
65801
65802 function uiConfirm(selection) {
65803     var modalSelection = uiModal(selection);
65804
65805     modalSelection.select('.modal')
65806         .classed('modal-alert', true);
65807
65808     var section = modalSelection.select('.content');
65809
65810     section.append('div')
65811         .attr('class', 'modal-section header');
65812
65813     section.append('div')
65814         .attr('class', 'modal-section message-text');
65815
65816     var buttons = section.append('div')
65817         .attr('class', 'modal-section buttons cf');
65818
65819
65820     modalSelection.okButton = function() {
65821         buttons
65822             .append('button')
65823             .attr('class', 'action col4')
65824             .on('click.confirm', function() {
65825                 modalSelection.remove();
65826             })
65827             .text(t('confirm.okay'));
65828
65829         return modalSelection;
65830     };
65831
65832
65833     return modalSelection;
65834 }
65835
65836 function uiConflicts(context) {
65837     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
65838         list;
65839
65840
65841     function conflicts(selection$$1) {
65842         var header = selection$$1
65843             .append('div')
65844             .attr('class', 'header fillL');
65845
65846         header
65847             .append('button')
65848             .attr('class', 'fr')
65849             .on('click', function() { dispatch$$1.call('cancel'); })
65850             .call(svgIcon('#icon-close'));
65851
65852         header
65853             .append('h3')
65854             .text(t('save.conflict.header'));
65855
65856         var body = selection$$1
65857             .append('div')
65858             .attr('class', 'body fillL');
65859
65860         body
65861             .append('div')
65862             .attr('class', 'conflicts-help')
65863             .text(t('save.conflict.help'))
65864             .append('a')
65865             .attr('class', 'conflicts-download')
65866             .text(t('save.conflict.download_changes'))
65867             .on('click.download', function() { dispatch$$1.call('download'); });
65868
65869         body
65870             .append('div')
65871             .attr('class', 'conflict-container fillL3')
65872             .call(showConflict, 0);
65873
65874         body
65875             .append('div')
65876             .attr('class', 'conflicts-done')
65877             .attr('opacity', 0)
65878             .style('display', 'none')
65879             .text(t('save.conflict.done'));
65880
65881         var buttons = body
65882             .append('div')
65883             .attr('class','buttons col12 joined conflicts-buttons');
65884
65885         buttons
65886             .append('button')
65887             .attr('disabled', list.length > 1)
65888             .attr('class', 'action conflicts-button col6')
65889             .text(t('save.title'))
65890             .on('click.try_again', function() { dispatch$$1.call('save'); });
65891
65892         buttons
65893             .append('button')
65894             .attr('class', 'secondary-action conflicts-button col6')
65895             .text(t('confirm.cancel'))
65896             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65897     }
65898
65899
65900     function showConflict(selection$$1, index) {
65901         if (index < 0 || index >= list.length) return;
65902
65903         var parent = select(selection$$1.node().parentNode);
65904
65905         // enable save button if this is the last conflict being reviewed..
65906         if (index === list.length - 1) {
65907             window.setTimeout(function() {
65908                 parent.select('.conflicts-button')
65909                     .attr('disabled', null);
65910
65911                 parent.select('.conflicts-done')
65912                     .transition()
65913                     .attr('opacity', 1)
65914                     .style('display', 'block');
65915             }, 250);
65916         }
65917
65918         var item = selection$$1
65919             .selectAll('.conflict')
65920             .data([list[index]]);
65921
65922         var enter = item.enter()
65923             .append('div')
65924             .attr('class', 'conflict');
65925
65926         enter
65927             .append('h4')
65928             .attr('class', 'conflict-count')
65929             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
65930
65931         enter
65932             .append('a')
65933             .attr('class', 'conflict-description')
65934             .attr('href', '#')
65935             .text(function(d) { return d.name; })
65936             .on('click', function(d) {
65937                 zoomToEntity(d.id);
65938                 event.preventDefault();
65939             });
65940
65941         var details = enter
65942             .append('div')
65943             .attr('class', 'conflict-detail-container');
65944
65945         details
65946             .append('ul')
65947             .attr('class', 'conflict-detail-list')
65948             .selectAll('li')
65949             .data(function(d) { return d.details || []; })
65950             .enter()
65951             .append('li')
65952             .attr('class', 'conflict-detail-item')
65953             .html(function(d) { return d; });
65954
65955         details
65956             .append('div')
65957             .attr('class', 'conflict-choices')
65958             .call(addChoices);
65959
65960         details
65961             .append('div')
65962             .attr('class', 'conflict-nav-buttons joined cf')
65963             .selectAll('button')
65964             .data(['previous', 'next'])
65965             .enter()
65966             .append('button')
65967             .text(function(d) { return t('save.conflict.' + d); })
65968             .attr('class', 'conflict-nav-button action col6')
65969             .attr('disabled', function(d, i) {
65970                 return (i === 0 && index === 0) ||
65971                     (i === 1 && index === list.length - 1) || null;
65972             })
65973             .on('click', function(d, i) {
65974                 var container = parent.select('.conflict-container'),
65975                 sign = (i === 0 ? -1 : 1);
65976
65977                 container
65978                     .selectAll('.conflict')
65979                     .remove();
65980
65981                 container
65982                     .call(showConflict, index + sign);
65983
65984                 event.preventDefault();
65985             });
65986
65987         item.exit()
65988             .remove();
65989     }
65990
65991
65992     function addChoices(selection$$1) {
65993         var choices = selection$$1
65994             .append('ul')
65995             .attr('class', 'layer-list')
65996             .selectAll('li')
65997             .data(function(d) { return d.choices || []; });
65998
65999         var enter = choices.enter()
66000             .append('li')
66001             .attr('class', 'layer');
66002
66003         var label = enter
66004             .append('label');
66005
66006         label
66007             .append('input')
66008             .attr('type', 'radio')
66009             .attr('name', function(d) { return d.id; })
66010             .on('change', function(d, i) {
66011                 var ul = this.parentNode.parentNode.parentNode;
66012                 ul.__data__.chosen = i;
66013                 choose(ul, d);
66014             });
66015
66016         label
66017             .append('span')
66018             .text(function(d) { return d.text; });
66019
66020         choices
66021             .each(function(d, i) {
66022                 var ul = this.parentNode;
66023                 if (ul.__data__.chosen === i) choose(ul, d);
66024             });
66025     }
66026
66027
66028     function choose(ul, datum) {
66029         if (event) event.preventDefault();
66030
66031         select(ul)
66032             .selectAll('li')
66033             .classed('active', function(d) { return d === datum; })
66034             .selectAll('input')
66035             .property('checked', function(d) { return d === datum; });
66036
66037         var extent$$1 = geoExtent$$1(),
66038             entity;
66039
66040         entity = context.graph().hasEntity(datum.id);
66041         if (entity) extent$$1._extend(entity.extent(context.graph()));
66042
66043         datum.action();
66044
66045         entity = context.graph().hasEntity(datum.id);
66046         if (entity) extent$$1._extend(entity.extent(context.graph()));
66047
66048         zoomToEntity(datum.id, extent$$1);
66049     }
66050
66051
66052     function zoomToEntity(id, extent$$1) {
66053         context.surface().selectAll('.hover')
66054             .classed('hover', false);
66055
66056         var entity = context.graph().hasEntity(id);
66057         if (entity) {
66058             if (extent$$1) {
66059                 context.map().trimmedExtent(extent$$1);
66060             } else {
66061                 context.map().zoomTo(entity);
66062             }
66063             context.surface().selectAll(
66064                 utilEntityOrMemberSelector([entity.id], context.graph()))
66065                 .classed('hover', true);
66066         }
66067     }
66068
66069
66070     // The conflict list should be an array of objects like:
66071     // {
66072     //     id: id,
66073     //     name: entityName(local),
66074     //     details: merge.conflicts(),
66075     //     chosen: 1,
66076     //     choices: [
66077     //         choice(id, keepMine, forceLocal),
66078     //         choice(id, keepTheirs, forceRemote)
66079     //     ]
66080     // }
66081     conflicts.list = function(_) {
66082         if (!arguments.length) return list;
66083         list = _;
66084         return conflicts;
66085     };
66086
66087
66088     return utilRebind(conflicts, dispatch$$1, 'on');
66089 }
66090
66091 function uiFlash(selection) {
66092     var modalSelection = uiModal(selection);
66093
66094     modalSelection.select('.modal')
66095         .classed('modal-flash', true);
66096
66097     modalSelection.select('.content')
66098         .classed('modal-section', true)
66099         .append('div')
66100         .attr('class', 'description');
66101
66102     modalSelection.on('click.flash', function() {
66103         modalSelection.remove();
66104     });
66105
66106     setTimeout(function() {
66107         modalSelection.remove();
66108         return true;
66109     }, 1500);
66110
66111
66112     return modalSelection;
66113 }
66114
66115 function uiLasso(context) {
66116     var group, polygon;
66117
66118     lasso.coordinates = [];
66119
66120     function lasso(selection$$1) {
66121         context.container()
66122             .classed('lasso', true);
66123
66124         group = selection$$1
66125             .append('g')
66126             .attr('class', 'lasso hide');
66127
66128         polygon = group
66129             .append('path')
66130             .attr('class', 'lasso-path');
66131
66132         group
66133             .call(uiToggle(true));
66134     }
66135
66136
66137     function draw() {
66138         if (polygon) {
66139             polygon.data([lasso.coordinates])
66140                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
66141         }
66142     }
66143
66144
66145     lasso.extent = function () {
66146         return lasso.coordinates.reduce(function(extent$$1, point) {
66147             return extent$$1.extend(geoExtent$$1(point));
66148         }, geoExtent$$1());
66149     };
66150
66151
66152     lasso.p = function(_) {
66153         if (!arguments.length) return lasso;
66154         lasso.coordinates.push(_);
66155         draw();
66156         return lasso;
66157     };
66158
66159
66160     lasso.close = function() {
66161         if (group) {
66162             group.call(uiToggle(false, function() {
66163                 select(this).remove();
66164             }));
66165         }
66166         context.container().classed('lasso', false);
66167     };
66168
66169
66170     return lasso;
66171 }
66172
66173 function uiRadialMenu(context, operations) {
66174     var menu,
66175         center = [0, 0],
66176         tooltip;
66177
66178
66179     var radialMenu = function(selection$$1) {
66180         if (!operations.length) return;
66181
66182         selection$$1.node().parentNode.focus();
66183
66184         function click(operation) {
66185             event.stopPropagation();
66186             if (operation.disabled()) return;
66187             operation();
66188             radialMenu.close();
66189         }
66190
66191         menu = selection$$1
66192             .append('g')
66193             .attr('class', 'radial-menu')
66194             .attr('transform', 'translate(' + center + ')')
66195             .attr('opacity', 0);
66196
66197         menu
66198             .transition()
66199             .attr('opacity', 1);
66200
66201         var r = 50,
66202             a = Math.PI / 4,
66203             a0 = -Math.PI / 4,
66204             a1 = a0 + (operations.length - 1) * a;
66205
66206         menu
66207             .append('path')
66208             .attr('class', 'radial-menu-background')
66209             .attr('d', 'M' + r * Math.sin(a0) + ',' +
66210                              r * Math.cos(a0) +
66211                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
66212                              (r * Math.sin(a1) + 1e-3) + ',' +
66213                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
66214             .attr('stroke-width', 50)
66215             .attr('stroke-linecap', 'round');
66216
66217         var button = menu.selectAll()
66218             .data(operations)
66219             .enter()
66220             .append('g')
66221             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
66222             .classed('disabled', function(d) { return d.disabled(); })
66223             .attr('transform', function(d, i) {
66224                 return 'translate(' + geoRoundCoords([
66225                         r * Math.sin(a0 + i * a),
66226                         r * Math.cos(a0 + i * a)]).join(',') + ')';
66227             });
66228
66229         button
66230             .append('circle')
66231             .attr('r', 15)
66232             .on('click', click)
66233             .on('mousedown', mousedown)
66234             .on('mouseover', mouseover)
66235             .on('mouseout', mouseout);
66236
66237         button
66238             .append('use')
66239             .attr('transform', 'translate(-10,-10)')
66240             .attr('width', '20')
66241             .attr('height', '20')
66242             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
66243
66244         tooltip = select(document.body)
66245             .append('div')
66246             .attr('class', 'tooltip-inner radial-menu-tooltip');
66247
66248         function mousedown() {
66249             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
66250         }
66251
66252         function mouseover(d, i) {
66253             var rect = context.surfaceRect(),
66254                 angle = a0 + i * a,
66255                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
66256                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
66257                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
66258                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
66259
66260             tooltip
66261                 .style('top', null)
66262                 .style('left', null)
66263                 .style('bottom', null)
66264                 .style('right', null)
66265                 .style('display', 'block')
66266                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
66267
66268             if (i === 0) {
66269                 tooltip
66270                     .style('right', right)
66271                     .style('top', top);
66272             } else if (i >= 4) {
66273                 tooltip
66274                     .style('left', left)
66275                     .style('bottom', bottom);
66276             } else {
66277                 tooltip
66278                     .style('left', left)
66279                     .style('top', top);
66280             }
66281         }
66282
66283         function mouseout() {
66284             tooltip.style('display', 'none');
66285         }
66286     };
66287
66288
66289     radialMenu.close = function() {
66290         if (menu) {
66291             menu
66292                 .style('pointer-events', 'none')
66293                 .transition()
66294                 .attr('opacity', 0)
66295                 .remove();
66296         }
66297
66298         if (tooltip) {
66299             tooltip.remove();
66300         }
66301     };
66302
66303
66304     radialMenu.center = function(_) {
66305         if (!arguments.length) return center;
66306         center = _;
66307         return radialMenu;
66308     };
66309
66310
66311     return radialMenu;
66312 }
66313
66314 function uiSelectionList(context, selectedIDs) {
66315
66316     function selectEntity(entity) {
66317         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
66318     }
66319
66320
66321     function deselectEntity(entity) {
66322         event.stopPropagation();
66323         var index = selectedIDs.indexOf(entity.id);
66324         if (index > -1) {
66325             selectedIDs.splice(index, 1);
66326         }
66327         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
66328     }
66329
66330
66331     function selectionList(selection$$1) {
66332         selection$$1.classed('selection-list-pane', true);
66333
66334         var header = selection$$1
66335             .append('div')
66336             .attr('class', 'header fillL cf');
66337
66338         header
66339             .append('h3')
66340             .text(t('inspector.multiselect'));
66341
66342         var listWrap = selection$$1
66343             .append('div')
66344             .attr('class', 'inspector-body');
66345
66346         var list = listWrap
66347             .append('div')
66348             .attr('class', 'feature-list cf');
66349
66350         context.history().on('change.selection-list', drawList);
66351         drawList();
66352
66353
66354         function drawList() {
66355             var entities = selectedIDs
66356                 .map(function(id) { return context.hasEntity(id); })
66357                 .filter(function(entity) { return entity; });
66358
66359             var items = list.selectAll('.feature-list-item')
66360                 .data(entities, osmEntity$$1.key);
66361
66362             items.exit()
66363                 .remove();
66364
66365             // Enter
66366             var enter = items.enter()
66367                 .append('div')
66368                 .attr('class', 'feature-list-item')
66369                 .on('click', selectEntity);
66370
66371             var label = enter
66372                 .append('button')
66373                 .attr('class', 'label');
66374
66375             enter
66376                 .append('button')
66377                 .attr('class', 'close')
66378                 .on('click', deselectEntity)
66379                 .call(svgIcon('#icon-close'));
66380
66381             label
66382                 .append('span')
66383                 .attr('class', 'entity-geom-icon')
66384                 .call(svgIcon('', 'pre-text'));
66385
66386             label
66387                 .append('span')
66388                 .attr('class', 'entity-type');
66389
66390             label
66391                 .append('span')
66392                 .attr('class', 'entity-name');
66393
66394             // Update
66395             items = items.merge(enter);
66396
66397             items.selectAll('.entity-geom-icon use')
66398                 .attr('href', function() {
66399                     var entity = this.parentNode.parentNode.__data__;
66400                     return '#icon-' + context.geometry(entity.id);
66401                 });
66402
66403             items.selectAll('.entity-type')
66404                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
66405
66406             items.selectAll('.entity-name')
66407                 .text(function(entity) { return utilDisplayName(entity); });
66408         }
66409     }
66410
66411     return selectionList;
66412 }
66413
66414 function uiSourceSwitch(context) {
66415     var keys$$1;
66416
66417
66418     function click() {
66419         event.preventDefault();
66420
66421         if (context.history().hasChanges() &&
66422             !window.confirm(t('source_switch.lose_changes'))) return;
66423
66424         var live = select(this)
66425             .classed('live');
66426
66427         context.connection()
66428             .switch(live ? keys$$1[1] : keys$$1[0]);
66429
66430         context.enter(modeBrowse(context));
66431         context.flush();
66432
66433         select(this)
66434             .text(live ? t('source_switch.dev') : t('source_switch.live'))
66435             .classed('live', !live);
66436     }
66437
66438     var sourceSwitch = function(selection$$1) {
66439         selection$$1
66440             .append('a')
66441             .attr('href', '#')
66442             .text(t('source_switch.live'))
66443             .classed('live', true)
66444             .attr('tabindex', -1)
66445             .on('click', click);
66446     };
66447
66448
66449     sourceSwitch.keys = function(_) {
66450         if (!arguments.length) return keys$$1;
66451         keys$$1 = _;
66452         return sourceSwitch;
66453     };
66454
66455
66456     return sourceSwitch;
66457 }
66458
66459 function uiSuccess(context) {
66460     var dispatch$$1 = dispatch('cancel'),
66461         changeset;
66462
66463
66464     function success(selection$$1) {
66465         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
66466             ' ' + context.connection().changesetURL(changeset.id);
66467
66468         var header = selection$$1
66469             .append('div')
66470             .attr('class', 'header fillL');
66471
66472         header
66473             .append('button')
66474             .attr('class', 'fr')
66475             .on('click', function() { dispatch$$1.call('cancel'); })
66476             .call(svgIcon('#icon-close'));
66477
66478         header
66479             .append('h3')
66480             .text(t('success.just_edited'));
66481
66482         var body = selection$$1
66483             .append('div')
66484             .attr('class', 'body save-success fillL');
66485
66486         body
66487             .append('p')
66488             .html(t('success.help_html'));
66489
66490         body
66491             .append('a')
66492             .attr('class', 'details')
66493             .attr('target', '_blank')
66494             .attr('tabindex', -1)
66495             .call(svgIcon('#icon-out-link', 'inline'))
66496             .attr('href', t('success.help_link_url'))
66497             .append('span')
66498             .text(t('success.help_link_text'));
66499
66500         var changesetURL = context.connection().changesetURL(changeset.id);
66501
66502         body
66503             .append('a')
66504             .attr('class', 'button col12 osm')
66505             .attr('target', '_blank')
66506             .attr('href', changesetURL)
66507             .text(t('success.view_on_osm'));
66508
66509         var sharing = {
66510             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
66511             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
66512             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
66513         };
66514
66515         body.selectAll('.button.social')
66516             .data(entries(sharing))
66517             .enter()
66518             .append('a')
66519             .attr('class', 'button social col4')
66520             .attr('target', '_blank')
66521             .attr('href', function(d) { return d.value; })
66522             .call(tooltip()
66523                 .title(function(d) { return t('success.' + d.key); })
66524                 .placement('bottom'))
66525             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
66526     }
66527
66528
66529     success.changeset = function(_) {
66530         if (!arguments.length) return changeset;
66531         changeset = _;
66532         return success;
66533     };
66534
66535
66536     return utilRebind(success, dispatch$$1, 'on');
66537 }
66538
66539 function coreHistory(context) {
66540     var imageryUsed = ['Bing'],
66541         dispatch$$1 = dispatch('change', 'undone', 'redone'),
66542         lock = utilSessionMutex('lock'),
66543         duration = 150,
66544         stack$$1, index, tree$$1;
66545
66546
66547     // internal _act, accepts list of actions and eased time
66548     function _act(actions, t) {
66549         actions = Array.prototype.slice.call(actions);
66550
66551         var annotation;
66552
66553         if (!lodash.isFunction(lodash.last(actions))) {
66554             annotation = actions.pop();
66555         }
66556
66557         stack$$1[index].transform = context.projection.transform();
66558         stack$$1[index].selectedIDs = context.selectedIDs();
66559
66560         var graph = stack$$1[index].graph;
66561         for (var i = 0; i < actions.length; i++) {
66562             graph = actions[i](graph, t);
66563         }
66564
66565         return {
66566             graph: graph,
66567             annotation: annotation,
66568             imageryUsed: imageryUsed
66569         };
66570     }
66571
66572
66573     // internal _perform with eased time
66574     function _perform(args, t) {
66575         var previous = stack$$1[index].graph;
66576         stack$$1 = stack$$1.slice(0, index + 1);
66577         stack$$1.push(_act(args, t));
66578         index++;
66579         return change(previous);
66580     }
66581
66582
66583     // internal _replace with eased time
66584     function _replace(args, t) {
66585         var previous = stack$$1[index].graph;
66586         // assert(index == stack.length - 1)
66587         stack$$1[index] = _act(args, t);
66588         return change(previous);
66589     }
66590
66591
66592     // internal _overwrite with eased time
66593     function _overwrite(args, t) {
66594         var previous = stack$$1[index].graph;
66595         if (index > 0) {
66596             index--;
66597             stack$$1.pop();
66598         }
66599         stack$$1 = stack$$1.slice(0, index + 1);
66600         stack$$1.push(_act(args, t));
66601         index++;
66602         return change(previous);
66603     }
66604
66605
66606     // determine diffrence and dispatch a change event
66607     function change(previous) {
66608         var difference = coreDifference(previous, history.graph());
66609         dispatch$$1.call('change', this, difference);
66610         return difference;
66611     }
66612
66613
66614     // iD uses namespaced keys so multiple installations do not conflict
66615     function getKey(n) {
66616         return 'iD_' + window.location.origin + '_' + n;
66617     }
66618
66619
66620     var history = {
66621
66622         graph: function() {
66623             return stack$$1[index].graph;
66624         },
66625
66626
66627         base: function() {
66628             return stack$$1[0].graph;
66629         },
66630
66631
66632         merge: function(entities, extent$$1) {
66633             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
66634             tree$$1.rebase(entities, false);
66635
66636             dispatch$$1.call('change', this, undefined, extent$$1);
66637         },
66638
66639
66640         perform: function() {
66641             // complete any transition already in progress
66642             select(document).interrupt('history.perform');
66643
66644             var transitionable = false,
66645                 action0 = arguments[0];
66646
66647             if (arguments.length === 1 ||
66648                 arguments.length === 2 && !lodash.isFunction(arguments[1])) {
66649                 transitionable = !!action0.transitionable;
66650             }
66651
66652             if (transitionable) {
66653                 var origArguments = arguments;
66654                 select(document)
66655                     .transition('history.perform')
66656                     .duration(duration)
66657                     .ease(linear$1)
66658                     .tween('history.tween', function() {
66659                         return function(t) {
66660                             if (t < 1) _overwrite([action0], t);
66661                         };
66662                     })
66663                     .on('start', function() {
66664                         _perform([action0], 0);
66665                     })
66666                     .on('end interrupt', function() {
66667                         _overwrite(origArguments, 1);
66668                     });
66669
66670             } else {
66671                 return _perform(arguments);
66672             }
66673         },
66674
66675
66676         replace: function() {
66677             select(document).interrupt('history.perform');
66678             return _replace(arguments, 1);
66679         },
66680
66681
66682         // Same as calling pop and then perform
66683         overwrite: function() {
66684             select(document).interrupt('history.perform');
66685             return _overwrite(arguments, 1);
66686         },
66687
66688
66689         pop: function() {
66690             select(document).interrupt('history.perform');
66691
66692             var previous = stack$$1[index].graph;
66693             if (index > 0) {
66694                 index--;
66695                 stack$$1.pop();
66696                 return change(previous);
66697             }
66698         },
66699
66700
66701         undo: function() {
66702             select(document).interrupt('history.perform');
66703
66704             var previous = stack$$1[index].graph;
66705
66706             // Pop to the next annotated state.
66707             while (index > 0) {
66708                 index--;
66709                 if (stack$$1[index].annotation) break;
66710             }
66711
66712             dispatch$$1.call('undone', this, stack$$1[index]);
66713             return change(previous);
66714         },
66715
66716
66717         redo: function() {
66718             select(document).interrupt('history.perform');
66719
66720             var previous = stack$$1[index].graph;
66721             while (index < stack$$1.length - 1) {
66722                 index++;
66723                 if (stack$$1[index].annotation) break;
66724             }
66725
66726             dispatch$$1.call('redone', this, stack$$1[index]);
66727             return change(previous);
66728         },
66729
66730
66731         undoAnnotation: function() {
66732             var i = index;
66733             while (i >= 0) {
66734                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66735                 i--;
66736             }
66737         },
66738
66739
66740         redoAnnotation: function() {
66741             var i = index + 1;
66742             while (i <= stack$$1.length - 1) {
66743                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
66744                 i++;
66745             }
66746         },
66747
66748
66749         intersects: function(extent$$1) {
66750             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
66751         },
66752
66753
66754         difference: function() {
66755             var base = stack$$1[0].graph,
66756                 head = stack$$1[index].graph;
66757             return coreDifference(base, head);
66758         },
66759
66760
66761         changes: function(action) {
66762             var base = stack$$1[0].graph,
66763                 head = stack$$1[index].graph;
66764
66765             if (action) {
66766                 head = action(head);
66767             }
66768
66769             var difference = coreDifference(base, head);
66770
66771             return {
66772                 modified: difference.modified(),
66773                 created: difference.created(),
66774                 deleted: difference.deleted()
66775             };
66776         },
66777
66778
66779         validate: function(changes) {
66780             return lodash(Validations)
66781                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
66782                 .flatten()
66783                 .value();
66784         },
66785
66786
66787         hasChanges: function() {
66788             return this.difference().length() > 0;
66789         },
66790
66791
66792         imageryUsed: function(sources) {
66793             if (sources) {
66794                 imageryUsed = sources;
66795                 return history;
66796             } else {
66797                 return lodash(stack$$1.slice(1, index + 1))
66798                     .map('imageryUsed')
66799                     .flatten()
66800                     .uniq()
66801                     .without(undefined, 'Custom')
66802                     .value();
66803             }
66804         },
66805
66806
66807         reset: function() {
66808             stack$$1 = [{graph: coreGraph$$1()}];
66809             index = 0;
66810             tree$$1 = coreTree(stack$$1[0].graph);
66811             dispatch$$1.call('change');
66812             return history;
66813         },
66814
66815
66816         toJSON: function() {
66817             if (!this.hasChanges()) return;
66818
66819             var allEntities = {},
66820                 baseEntities = {},
66821                 base = stack$$1[0];
66822
66823             var s = stack$$1.map(function(i) {
66824                 var modified = [], deleted = [];
66825
66826                 lodash.forEach(i.graph.entities, function(entity, id) {
66827                     if (entity) {
66828                         var key = osmEntity$$1.key(entity);
66829                         allEntities[key] = entity;
66830                         modified.push(key);
66831                     } else {
66832                         deleted.push(id);
66833                     }
66834
66835                     // make sure that the originals of changed or deleted entities get merged
66836                     // into the base of the stack after restoring the data from JSON.
66837                     if (id in base.graph.entities) {
66838                         baseEntities[id] = base.graph.entities[id];
66839                     }
66840                     // get originals of parent entities too
66841                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
66842                         if (parentId in base.graph.entities) {
66843                             baseEntities[parentId] = base.graph.entities[parentId];
66844                         }
66845                     });
66846                 });
66847
66848                 var x = {};
66849
66850                 if (modified.length) x.modified = modified;
66851                 if (deleted.length) x.deleted = deleted;
66852                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
66853                 if (i.annotation) x.annotation = i.annotation;
66854
66855                 return x;
66856             });
66857
66858             return JSON.stringify({
66859                 version: 3,
66860                 entities: lodash.values(allEntities),
66861                 baseEntities: lodash.values(baseEntities),
66862                 stack: s,
66863                 nextIDs: osmEntity$$1.id.next,
66864                 index: index
66865             });
66866         },
66867
66868
66869         fromJSON: function(json$$1, loadChildNodes) {
66870             var h = JSON.parse(json$$1),
66871                 loadComplete = true;
66872
66873             osmEntity$$1.id.next = h.nextIDs;
66874             index = h.index;
66875
66876             if (h.version === 2 || h.version === 3) {
66877                 var allEntities = {};
66878
66879                 h.entities.forEach(function(entity) {
66880                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
66881                 });
66882
66883                 if (h.version === 3) {
66884                     // This merges originals for changed entities into the base of
66885                     // the stack even if the current stack doesn't have them (for
66886                     // example when iD has been restarted in a different region)
66887                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
66888                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
66889                     tree$$1.rebase(baseEntities, true);
66890
66891                     // When we restore a modified way, we also need to fetch any missing
66892                     // childnodes that would normally have been downloaded with it.. #2142
66893                     if (loadChildNodes) {
66894                         var missing =  lodash(baseEntities)
66895                                 .filter({ type: 'way' })
66896                                 .map('nodes')
66897                                 .flatten()
66898                                 .uniq()
66899                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
66900                                 .value();
66901
66902                         if (!lodash.isEmpty(missing)) {
66903                             loadComplete = false;
66904                             context.redrawEnable(false);
66905
66906                             var loading = uiLoading(context).blocking(true);
66907                             context.container().call(loading);
66908
66909                             var childNodesLoaded = function(err, result) {
66910                                 if (!err) {
66911                                     var visible = lodash.groupBy(result.data, 'visible');
66912                                     if (!lodash.isEmpty(visible.true)) {
66913                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
66914                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
66915                                         tree$$1.rebase(visible.true, true);
66916                                     }
66917
66918                                     // fetch older versions of nodes that were deleted..
66919                                     lodash.each(visible.false, function(entity) {
66920                                         context.connection()
66921                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
66922                                     });
66923                                 }
66924
66925                                 if (err || lodash.isEmpty(missing)) {
66926                                     loading.close();
66927                                     context.redrawEnable(true);
66928                                     dispatch$$1.call('change');
66929                                 }
66930                             };
66931
66932                             context.connection().loadMultiple(missing, childNodesLoaded);
66933                         }
66934                     }
66935                 }
66936
66937                 stack$$1 = h.stack.map(function(d) {
66938                     var entities = {}, entity;
66939
66940                     if (d.modified) {
66941                         d.modified.forEach(function(key) {
66942                             entity = allEntities[key];
66943                             entities[entity.id] = entity;
66944                         });
66945                     }
66946
66947                     if (d.deleted) {
66948                         d.deleted.forEach(function(id) {
66949                             entities[id] = undefined;
66950                         });
66951                     }
66952
66953                     return {
66954                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
66955                         annotation: d.annotation,
66956                         imageryUsed: d.imageryUsed
66957                     };
66958                 });
66959
66960             } else { // original version
66961                 stack$$1 = h.stack.map(function(d) {
66962                     var entities = {};
66963
66964                     for (var i in d.entities) {
66965                         var entity = d.entities[i];
66966                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
66967                     }
66968
66969                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
66970                     return d;
66971                 });
66972             }
66973
66974             if (loadComplete) {
66975                 dispatch$$1.call('change');
66976             }
66977
66978             return history;
66979         },
66980
66981
66982         save: function() {
66983             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
66984             return history;
66985         },
66986
66987
66988         clearSaved: function() {
66989             context.debouncedSave.cancel();
66990             if (lock.locked()) context.storage(getKey('saved_history'), null);
66991             return history;
66992         },
66993
66994
66995         lock: function() {
66996             return lock.lock();
66997         },
66998
66999
67000         unlock: function() {
67001             lock.unlock();
67002         },
67003
67004
67005         // is iD not open in another window and it detects that
67006         // there's a history stored in localStorage that's recoverable?
67007         restorableChanges: function() {
67008             return lock.locked() && !!context.storage(getKey('saved_history'));
67009         },
67010
67011
67012         // load history from a version stored in localStorage
67013         restore: function() {
67014             if (!lock.locked()) return;
67015
67016             var json$$1 = context.storage(getKey('saved_history'));
67017             if (json$$1) history.fromJSON(json$$1, true);
67018         },
67019
67020
67021         _getKey: getKey
67022
67023     };
67024
67025
67026     history.reset();
67027
67028     return utilRebind(history, dispatch$$1, 'on');
67029 }
67030
67031 function presetCollection(collection) {
67032     var maxSearchResults = 50,
67033         maxSuggestionResults = 10;
67034
67035     var presets = {
67036
67037         collection: collection,
67038
67039
67040         item: function(id) {
67041             return lodash.find(collection, function(d) {
67042                 return d.id === id;
67043             });
67044         },
67045
67046
67047         matchGeometry: function(geometry) {
67048             return presetCollection(collection.filter(function(d) {
67049                 return d.matchGeometry(geometry);
67050             }));
67051         },
67052
67053
67054         search: function(value, geometry) {
67055             if (!value) return this;
67056
67057             function leading(a) {
67058                 var index = a.indexOf(value);
67059                 return index === 0 || a[index - 1] === ' ';
67060             }
67061
67062             function suggestionName(name) {
67063                 var nameArray = name.split(' - ');
67064                 if (nameArray.length > 1) {
67065                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
67066                 }
67067                 return name.toLowerCase();
67068             }
67069
67070
67071             value = value.toLowerCase();
67072
67073             var searchable = lodash.filter(collection, function(a) {
67074                     return a.searchable !== false && a.suggestion !== true;
67075                 }),
67076                 suggestions = lodash.filter(collection, function(a) {
67077                     return a.suggestion === true;
67078                 });
67079
67080
67081             // matches value to preset.name
67082             var leading_name = lodash.filter(searchable, function(a) {
67083                     return leading(a.name().toLowerCase());
67084                 }).sort(function(a, b) {
67085                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
67086                     if (i === 0) return a.name().length - b.name().length;
67087                     else return i;
67088                 });
67089
67090             // matches value to preset.terms values
67091             var leading_terms = lodash.filter(searchable, function(a) {
67092                     return lodash.some(a.terms() || [], leading);
67093                 });
67094
67095             // matches value to preset.tags values
67096             var leading_tag_values = lodash.filter(searchable, function(a) {
67097                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
67098                 });
67099
67100
67101             // finds close matches to value in preset.name
67102             var similar_name = searchable.map(function(a) {
67103                     return {
67104                         preset: a,
67105                         dist: utilEditDistance(value, a.name())
67106                     };
67107                 }).filter(function(a) {
67108                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
67109                 }).sort(function(a, b) {
67110                     return a.dist - b.dist;
67111                 }).map(function(a) {
67112                     return a.preset;
67113                 });
67114
67115             // finds close matches to value in preset.terms
67116             var similar_terms = lodash.filter(searchable, function(a) {
67117                     return lodash.some(a.terms() || [], function(b) {
67118                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
67119                     });
67120                 });
67121
67122             var leading_suggestions = lodash.filter(suggestions, function(a) {
67123                     return leading(suggestionName(a.name()));
67124                 }).sort(function(a, b) {
67125                     a = suggestionName(a.name());
67126                     b = suggestionName(b.name());
67127                     var i = a.indexOf(value) - b.indexOf(value);
67128                     if (i === 0) return a.length - b.length;
67129                     else return i;
67130                 });
67131
67132             var similar_suggestions = suggestions.map(function(a) {
67133                     return {
67134                         preset: a,
67135                         dist: utilEditDistance(value, suggestionName(a.name()))
67136                     };
67137                 }).filter(function(a) {
67138                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
67139                 }).sort(function(a, b) {
67140                     return a.dist - b.dist;
67141                 }).map(function(a) {
67142                     return a.preset;
67143                 });
67144
67145             var other = presets.item(geometry);
67146
67147             var results = leading_name.concat(
67148                     leading_terms,
67149                     leading_tag_values,
67150                     leading_suggestions.slice(0, maxSuggestionResults + 5),
67151                     similar_name,
67152                     similar_terms,
67153                     similar_suggestions.slice(0, maxSuggestionResults)
67154                 ).slice(0, maxSearchResults - 1);
67155
67156             return presetCollection(lodash.uniq(results.concat(other)));
67157         }
67158     };
67159
67160
67161     return presets;
67162 }
67163
67164 function presetCategory(id, category, all) {
67165     category = lodash.clone(category);
67166
67167     category.id = id;
67168
67169
67170     category.members = presetCollection(category.members.map(function(id) {
67171         return all.item(id);
67172     }));
67173
67174
67175     category.matchGeometry = function(geometry) {
67176         return category.geometry.indexOf(geometry) >= 0;
67177     };
67178
67179
67180     category.matchScore = function() {
67181         return -1;
67182     };
67183
67184
67185     category.name = function() {
67186         return t('presets.categories.' + id + '.name', {'default': id});
67187     };
67188
67189
67190     category.terms = function() {
67191         return [];
67192     };
67193
67194
67195     return category;
67196 }
67197
67198 function presetField(id, field) {
67199     field = lodash.clone(field);
67200
67201     field.id = id;
67202
67203
67204     field.matchGeometry = function(geometry) {
67205         return !field.geometry || field.geometry === geometry;
67206     };
67207
67208
67209     field.t = function(scope, options) {
67210         return t('presets.fields.' + id + '.' + scope, options);
67211     };
67212
67213
67214     field.label = function() {
67215         return field.t('label', {'default': id});
67216     };
67217
67218
67219     var placeholder = field.placeholder;
67220     field.placeholder = function() {
67221         return field.t('placeholder', {'default': placeholder});
67222     };
67223
67224
67225     return field;
67226 }
67227
67228 function presetPreset(id, preset, fields) {
67229     preset = lodash.clone(preset);
67230
67231     preset.id = id;
67232     preset.fields = (preset.fields || []).map(getFields);
67233     preset.geometry = (preset.geometry || []);
67234
67235
67236     function getFields(f) {
67237         return fields[f];
67238     }
67239
67240
67241     preset.matchGeometry = function(geometry) {
67242         return preset.geometry.indexOf(geometry) >= 0;
67243     };
67244
67245
67246     var matchScore = preset.matchScore || 1;
67247     preset.matchScore = function(entity) {
67248         var tags = preset.tags,
67249             score = 0;
67250
67251         for (var t$$1 in tags) {
67252             if (entity.tags[t$$1] === tags[t$$1]) {
67253                 score += matchScore;
67254             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
67255                 score += matchScore / 2;
67256             } else {
67257                 return -1;
67258             }
67259         }
67260
67261         return score;
67262     };
67263
67264
67265     preset.t = function(scope, options) {
67266         return t('presets.presets.' + id + '.' + scope, options);
67267     };
67268
67269
67270     var name = preset.name || '';
67271     preset.name = function() {
67272         if (preset.suggestion) {
67273             id = id.split('/');
67274             id = id[0] + '/' + id[1];
67275             return name + ' - ' + t('presets.presets.' + id + '.name');
67276         }
67277         return preset.t('name', {'default': name});
67278     };
67279
67280
67281     preset.terms = function() {
67282         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
67283     };
67284
67285
67286     preset.isFallback = function() {
67287         var tagCount = Object.keys(preset.tags).length;
67288         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
67289     };
67290
67291
67292     preset.reference = function(geometry) {
67293         var key = Object.keys(preset.tags)[0],
67294             value = preset.tags[key];
67295
67296         if (geometry === 'relation' && key === 'type') {
67297             if (value in preset.tags) {
67298                 key = value;
67299                 value = preset.tags[key];
67300             } else {
67301                 return { rtype: value };
67302             }
67303         }
67304
67305         if (value === '*') {
67306             return { key: key };
67307         } else {
67308             return { key: key, value: value };
67309         }
67310     };
67311
67312
67313     var removeTags = preset.removeTags || preset.tags;
67314     preset.removeTags = function(tags, geometry) {
67315         tags = lodash.omit(tags, lodash.keys(removeTags));
67316
67317         for (var f in preset.fields) {
67318             var field = preset.fields[f];
67319             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
67320                 delete tags[field.key];
67321             }
67322         }
67323
67324         delete tags.area;
67325         return tags;
67326     };
67327
67328
67329     var applyTags = preset.addTags || preset.tags;
67330     preset.applyTags = function(tags, geometry) {
67331         var k;
67332
67333         tags = lodash.clone(tags);
67334
67335         for (k in applyTags) {
67336             if (applyTags[k] === '*') {
67337                 tags[k] = 'yes';
67338             } else {
67339                 tags[k] = applyTags[k];
67340             }
67341         }
67342
67343         // Add area=yes if necessary.
67344         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
67345         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
67346         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
67347         if (geometry === 'area') {
67348             var needsAreaTag = true;
67349             if (preset.geometry.indexOf('line') === -1) {
67350                 for (k in applyTags) {
67351                     if (k in areaKeys) {
67352                         needsAreaTag = false;
67353                         break;
67354                     }
67355                 }
67356             }
67357             if (needsAreaTag) {
67358                 tags.area = 'yes';
67359             }
67360         }
67361
67362         for (var f in preset.fields) {
67363             var field = preset.fields[f];
67364             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
67365                 tags[field.key] = field.default;
67366             }
67367         }
67368
67369         return tags;
67370     };
67371
67372
67373     return preset;
67374 }
67375
67376 function presetIndex() {
67377     // a presetCollection with methods for
67378     // loading new data and returning defaults
67379
67380     var all = presetCollection([]),
67381         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
67382         fields = {},
67383         universal = [],
67384         recent = presetCollection([]);
67385
67386     // Index of presets by (geometry, tag key).
67387     var index = {
67388         point: {},
67389         vertex: {},
67390         line: {},
67391         area: {},
67392         relation: {}
67393     };
67394
67395     all.match = function(entity, resolver) {
67396         var geometry = entity.geometry(resolver);
67397
67398         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
67399         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
67400             geometry = 'point';
67401         }
67402
67403         var geometryMatches = index[geometry],
67404             best = -1,
67405             match;
67406
67407         for (var k in entity.tags) {
67408             var keyMatches = geometryMatches[k];
67409             if (!keyMatches) continue;
67410
67411             for (var i = 0; i < keyMatches.length; i++) {
67412                 var score = keyMatches[i].matchScore(entity);
67413                 if (score > best) {
67414                     best = score;
67415                     match = keyMatches[i];
67416                 }
67417             }
67418         }
67419
67420         return match || all.item(geometry);
67421     };
67422
67423
67424     // Because of the open nature of tagging, iD will never have a complete
67425     // list of tags used in OSM, so we want it to have logic like "assume
67426     // that a closed way with an amenity tag is an area, unless the amenity
67427     // is one of these specific types". This function computes a structure
67428     // that allows testing of such conditions, based on the presets designated
67429     // as as supporting (or not supporting) the area geometry.
67430     //
67431     // The returned object L is a whitelist/blacklist of tags. A closed way
67432     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
67433     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
67434     // and the subkeys form the blacklist.
67435     all.areaKeys = function() {
67436         var areaKeys = {},
67437             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
67438             presets = lodash.reject(all.collection, 'suggestion');
67439
67440         // whitelist
67441         presets.forEach(function(d) {
67442             for (var key in d.tags) break;
67443             if (!key) return;
67444             if (ignore.indexOf(key) !== -1) return;
67445
67446             if (d.geometry.indexOf('area') !== -1) {
67447                 areaKeys[key] = areaKeys[key] || {};
67448             }
67449         });
67450
67451         // blacklist
67452         presets.forEach(function(d) {
67453             for (var key in d.tags) break;
67454             if (!key) return;
67455             if (ignore.indexOf(key) !== -1) return;
67456
67457             var value = d.tags[key];
67458             if (d.geometry.indexOf('area') === -1 &&
67459                 d.geometry.indexOf('line') !== -1 &&
67460                 key in areaKeys && value !== '*') {
67461                 areaKeys[key][value] = true;
67462             }
67463         });
67464
67465         return areaKeys;
67466     };
67467
67468
67469     all.init = function() {
67470         var d = data.presets;
67471
67472         if (d.fields) {
67473             lodash.forEach(d.fields, function(d, id) {
67474                 fields[id] = presetField(id, d);
67475                 if (d.universal) universal.push(fields[id]);
67476             });
67477         }
67478
67479         if (d.presets) {
67480             lodash.forEach(d.presets, function(d, id) {
67481                 all.collection.push(presetPreset(id, d, fields));
67482             });
67483         }
67484
67485         if (d.categories) {
67486             lodash.forEach(d.categories, function(d, id) {
67487                 all.collection.push(presetCategory(id, d, all));
67488             });
67489         }
67490
67491         if (d.defaults) {
67492             var getItem = lodash.bind(all.item, all);
67493             defaults = {
67494                 area: presetCollection(d.defaults.area.map(getItem)),
67495                 line: presetCollection(d.defaults.line.map(getItem)),
67496                 point: presetCollection(d.defaults.point.map(getItem)),
67497                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
67498                 relation: presetCollection(d.defaults.relation.map(getItem))
67499             };
67500         }
67501
67502         for (var i = 0; i < all.collection.length; i++) {
67503             var preset = all.collection[i],
67504                 geometry = preset.geometry;
67505
67506             for (var j = 0; j < geometry.length; j++) {
67507                 var g = index[geometry[j]];
67508                 for (var k in preset.tags) {
67509                     (g[k] = g[k] || []).push(preset);
67510                 }
67511             }
67512         }
67513
67514         return all;
67515     };
67516
67517     all.field = function(id) {
67518         return fields[id];
67519     };
67520
67521     all.universal = function() {
67522         return universal;
67523     };
67524
67525     all.defaults = function(geometry, n) {
67526         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
67527             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
67528         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
67529     };
67530
67531     all.choose = function(preset) {
67532         if (!preset.isFallback()) {
67533             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
67534         }
67535         return all;
67536     };
67537
67538     return all;
67539 }
67540
67541 var areaKeys = {};
67542
67543 function setAreaKeys(value) {
67544     areaKeys = value;
67545 }
67546
67547
67548 function coreContext() {
67549
67550     // create a special translation that contains the keys in place of the strings
67551     var tkeys = lodash.cloneDeep(en);
67552     var parents = [];
67553
67554     function traverser(v, k, obj) {
67555         parents.push(k);
67556         if (lodash.isObject(v)) {
67557             lodash.forOwn(v, traverser);
67558         } else if (lodash.isString(v)) {
67559             obj[k] = parents.join('.');
67560         }
67561         parents.pop();
67562     }
67563
67564     lodash.forOwn(tkeys, traverser);
67565     addTranslation('_tkeys_', tkeys);
67566
67567     addTranslation('en', en);
67568     setLocale('en');
67569
67570     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
67571         context = {};
67572
67573     // https://github.com/openstreetmap/iD/issues/772
67574     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
67575     var storage;
67576     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
67577     storage = storage || (function() {
67578         var s = {};
67579         return {
67580             getItem: function(k) { return s[k]; },
67581             setItem: function(k, v) { s[k] = v; },
67582             removeItem: function(k) { delete s[k]; }
67583         };
67584     })();
67585
67586     context.storage = function(k, v) {
67587         try {
67588             if (arguments.length === 1) return storage.getItem(k);
67589             else if (v === null) storage.removeItem(k);
67590             else storage.setItem(k, v);
67591         } catch (e) {
67592             // localstorage quota exceeded
67593             /* eslint-disable no-console */
67594             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
67595             /* eslint-enable no-console */
67596         }
67597     };
67598
67599
67600     /* Straight accessors. Avoid using these if you can. */
67601     var ui, connection, history;
67602     context.ui = function() { return ui; };
67603     context.connection = function() { return connection; };
67604     context.history = function() { return history; };
67605
67606
67607     /* Connection */
67608     function entitiesLoaded(err, result) {
67609         if (!err) history.merge(result.data, result.extent);
67610     }
67611
67612     context.preauth = function(options) {
67613         connection.switch(options);
67614         return context;
67615     };
67616
67617     context.loadTiles = function(projection, dimensions, callback) {
67618         function done(err, result) {
67619             entitiesLoaded(err, result);
67620             if (callback) callback(err, result);
67621         }
67622         connection.loadTiles(projection, dimensions, done);
67623     };
67624
67625     context.loadEntity = function(id, callback) {
67626         function done(err, result) {
67627             entitiesLoaded(err, result);
67628             if (callback) callback(err, result);
67629         }
67630         connection.loadEntity(id, done);
67631     };
67632
67633     context.zoomToEntity = function(id, zoomTo) {
67634         if (zoomTo !== false) {
67635             this.loadEntity(id, function(err, result) {
67636                 if (err) return;
67637                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
67638                 if (entity) { map$$1.zoomTo(entity); }
67639             });
67640         }
67641
67642         map$$1.on('drawn.zoomToEntity', function() {
67643             if (!context.hasEntity(id)) return;
67644             map$$1.on('drawn.zoomToEntity', null);
67645             context.on('enter.zoomToEntity', null);
67646             context.enter(modeSelect(context, [id]));
67647         });
67648
67649         context.on('enter.zoomToEntity', function() {
67650             if (mode.id !== 'browse') {
67651                 map$$1.on('drawn.zoomToEntity', null);
67652                 context.on('enter.zoomToEntity', null);
67653             }
67654         });
67655     };
67656
67657     var minEditableZoom = 16;
67658     context.minEditableZoom = function(_) {
67659         if (!arguments.length) return minEditableZoom;
67660         minEditableZoom = _;
67661         connection.tileZoom(_);
67662         return context;
67663     };
67664
67665
67666     /* History */
67667     var inIntro = false;
67668     context.inIntro = function(_) {
67669         if (!arguments.length) return inIntro;
67670         inIntro = _;
67671         return context;
67672     };
67673
67674     context.save = function() {
67675         // no history save, no message onbeforeunload
67676         if (inIntro || select('.modal').size()) return;
67677
67678         var canSave;
67679         if (mode && mode.id === 'save') {
67680             canSave = false;
67681         } else {
67682             canSave = context.selectedIDs().every(function(id) {
67683                 var entity = context.hasEntity(id);
67684                 return entity && !entity.isDegenerate();
67685             });
67686         }
67687
67688         if (canSave) {
67689             history.save();
67690         }
67691         if (history.hasChanges()) {
67692             return t('save.unsaved_changes');
67693         }
67694     };
67695
67696
67697     /* Graph */
67698     context.hasEntity = function(id) {
67699         return history.graph().hasEntity(id);
67700     };
67701     context.entity = function(id) {
67702         return history.graph().entity(id);
67703     };
67704     context.childNodes = function(way) {
67705         return history.graph().childNodes(way);
67706     };
67707     context.geometry = function(id) {
67708         return context.entity(id).geometry(history.graph());
67709     };
67710
67711
67712     /* Modes */
67713     var mode;
67714     context.mode = function() {
67715         return mode;
67716     };
67717     context.enter = function(newMode) {
67718         if (mode) {
67719             mode.exit();
67720             dispatch$$1.call('exit', this, mode);
67721         }
67722
67723         mode = newMode;
67724         mode.enter();
67725         dispatch$$1.call('enter', this, mode);
67726     };
67727
67728     context.selectedIDs = function() {
67729         if (mode && mode.selectedIDs) {
67730             return mode.selectedIDs();
67731         } else {
67732             return [];
67733         }
67734     };
67735
67736
67737     /* Behaviors */
67738     context.install = function(behavior) {
67739         context.surface().call(behavior);
67740     };
67741     context.uninstall = function(behavior) {
67742         context.surface().call(behavior.off);
67743     };
67744
67745
67746     /* Copy/Paste */
67747     var copyIDs = [], copyGraph;
67748     context.copyGraph = function() { return copyGraph; };
67749     context.copyIDs = function(_) {
67750         if (!arguments.length) return copyIDs;
67751         copyIDs = _;
67752         copyGraph = history.graph();
67753         return context;
67754     };
67755
67756
67757     /* Background */
67758     var background;
67759     context.background = function() { return background; };
67760
67761
67762     /* Features */
67763     var features;
67764     context.features = function() { return features; };
67765     context.hasHiddenConnections = function(id) {
67766         var graph = history.graph(),
67767             entity = graph.entity(id);
67768         return features.hasHiddenConnections(entity, graph);
67769     };
67770
67771
67772     /* Presets */
67773     var presets;
67774     context.presets = function() { return presets; };
67775
67776
67777     /* Map */
67778     var map$$1;
67779     context.map = function() { return map$$1; };
67780     context.layers = function() { return map$$1.layers; };
67781     context.surface = function() { return map$$1.surface; };
67782     context.editable = function() { return map$$1.editable(); };
67783
67784     context.surfaceRect = function() {
67785         // Work around a bug in Firefox.
67786         //   http://stackoverflow.com/questions/18153989/
67787         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
67788         return context.surface().node().parentNode.getBoundingClientRect();
67789     };
67790
67791
67792     /* Debug */
67793     var debugFlags = {
67794         tile: false,
67795         collision: false,
67796         imagery: false,
67797         imperial: false,
67798         driveLeft: false
67799     };
67800     context.debugFlags = function() {
67801         return debugFlags;
67802     };
67803     context.setDebug = function(flag, val) {
67804         if (arguments.length === 1) val = true;
67805         debugFlags[flag] = val;
67806         dispatch$$1.call('change');
67807         return context;
67808     };
67809     context.getDebug = function(flag) {
67810         return flag && debugFlags[flag];
67811     };
67812
67813
67814     /* Container */
67815     var container, embed;
67816     context.container = function(_) {
67817         if (!arguments.length) return container;
67818         container = _;
67819         container.classed('id-container', true);
67820         return context;
67821     };
67822     context.embed = function(_) {
67823         if (!arguments.length) return embed;
67824         embed = _;
67825         return context;
67826     };
67827
67828
67829     /* Assets */
67830     var assetPath = '';
67831     context.assetPath = function(_) {
67832         if (!arguments.length) return assetPath;
67833         assetPath = _;
67834         return context;
67835     };
67836
67837     var assetMap = {};
67838     context.assetMap = function(_) {
67839         if (!arguments.length) return assetMap;
67840         assetMap = _;
67841         return context;
67842     };
67843
67844     context.asset = function(_) {
67845         var filename = assetPath + _;
67846         return assetMap[filename] || filename;
67847     };
67848
67849     context.imagePath = function(_) {
67850         return context.asset('img/' + _);
67851     };
67852
67853
67854     /* locales */
67855     // `locale` variable contains a "requested locale".
67856     // It won't become the `currentLocale` until after loadLocale() is called.
67857     var locale, localePath;
67858
67859     context.locale = function(loc, path$$1) {
67860         if (!arguments.length) return currentLocale;
67861         locale = loc;
67862         localePath = path$$1;
67863         return context;
67864     };
67865
67866     context.loadLocale = function(callback) {
67867         if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
67868             localePath = localePath || context.asset('locales/' + locale + '.json');
67869             json(localePath, function(err, result) {
67870                 if (!err) {
67871                     addTranslation(locale, result[locale]);
67872                     setLocale(locale);
67873                     utilDetect(true);
67874                 }
67875                 if (callback) {
67876                     callback(err);
67877                 }
67878             });
67879         } else {
67880             if (locale) {
67881                 setLocale(locale);
67882                 utilDetect(true);
67883             }
67884             if (callback) {
67885                 callback();
67886             }
67887         }
67888     };
67889
67890
67891     /* reset (aka flush) */
67892     context.reset = context.flush = function() {
67893         context.debouncedSave.cancel();
67894         lodash.each(services, function(service) {
67895             if (service && typeof service.reset === 'function') {
67896                 service.reset(context);
67897             }
67898         });
67899         features.reset();
67900         history.reset();
67901         return context;
67902     };
67903
67904
67905     /* Init */
67906     context.version = '2.1.0';
67907
67908     context.projection = geoRawMercator();
67909
67910     locale = utilDetect().locale;
67911     if (locale && !dataLocales.hasOwnProperty(locale)) {
67912         locale = locale.split('-')[0];
67913     }
67914
67915     history = coreHistory(context);
67916     context.graph = history.graph;
67917     context.changes = history.changes;
67918     context.intersects = history.intersects;
67919
67920     // Debounce save, since it's a synchronous localStorage write,
67921     // and history changes can happen frequently (e.g. when dragging).
67922     context.debouncedSave = lodash.debounce(context.save, 350);
67923     function withDebouncedSave(fn) {
67924         return function() {
67925             var result = fn.apply(history, arguments);
67926             context.debouncedSave();
67927             return result;
67928         };
67929     }
67930
67931     context.perform = withDebouncedSave(history.perform);
67932     context.replace = withDebouncedSave(history.replace);
67933     context.pop = withDebouncedSave(history.pop);
67934     context.overwrite = withDebouncedSave(history.overwrite);
67935     context.undo = withDebouncedSave(history.undo);
67936     context.redo = withDebouncedSave(history.redo);
67937
67938     ui = uiInit(context);
67939
67940     connection = services.osm;
67941     background = rendererBackground(context);
67942     features = rendererFeatures(context);
67943     presets = presetIndex();
67944
67945     map$$1 = rendererMap(context);
67946     context.mouse = map$$1.mouse;
67947     context.extent = map$$1.extent;
67948     context.pan = map$$1.pan;
67949     context.zoomIn = map$$1.zoomIn;
67950     context.zoomOut = map$$1.zoomOut;
67951     context.zoomInFurther = map$$1.zoomInFurther;
67952     context.zoomOutFurther = map$$1.zoomOutFurther;
67953     context.redrawEnable = map$$1.redrawEnable;
67954
67955     lodash.each(services, function(service) {
67956         if (service && typeof service.init === 'function') {
67957             service.init(context);
67958         }
67959     });
67960
67961     background.init();
67962     presets.init();
67963     areaKeys = presets.areaKeys();
67964
67965
67966     return utilRebind(context, dispatch$$1, 'on');
67967 }
67968
67969 function osmWay() {
67970     if (!(this instanceof osmWay)) {
67971         return (new osmWay()).initialize(arguments);
67972     } else if (arguments.length) {
67973         this.initialize(arguments);
67974     }
67975 }
67976
67977
67978 osmEntity$$1.way = osmWay;
67979
67980 osmWay.prototype = Object.create(osmEntity$$1.prototype);
67981
67982
67983 lodash.extend(osmWay.prototype, {
67984     type: 'way',
67985     nodes: [],
67986
67987
67988     copy: function(resolver, copies) {
67989         if (copies[this.id])
67990             return copies[this.id];
67991
67992         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
67993
67994         var nodes = this.nodes.map(function(id) {
67995             return resolver.entity(id).copy(resolver, copies).id;
67996         });
67997
67998         copy = copy.update({ nodes: nodes });
67999         copies[this.id] = copy;
68000
68001         return copy;
68002     },
68003
68004
68005     extent: function(resolver) {
68006         return resolver.transient(this, 'extent', function() {
68007             var extent$$1 = geoExtent$$1();
68008             for (var i = 0; i < this.nodes.length; i++) {
68009                 var node = resolver.hasEntity(this.nodes[i]);
68010                 if (node) {
68011                     extent$$1._extend(node.extent());
68012                 }
68013             }
68014             return extent$$1;
68015         });
68016     },
68017
68018
68019     first: function() {
68020         return this.nodes[0];
68021     },
68022
68023
68024     last: function() {
68025         return this.nodes[this.nodes.length - 1];
68026     },
68027
68028
68029     contains: function(node) {
68030         return this.nodes.indexOf(node) >= 0;
68031     },
68032
68033
68034     affix: function(node) {
68035         if (this.nodes[0] === node) return 'prefix';
68036         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
68037     },
68038
68039
68040     layer: function() {
68041         // explicit layer tag, clamp between -10, 10..
68042         if (isFinite(this.tags.layer)) {
68043             return Math.max(-10, Math.min(+(this.tags.layer), 10));
68044         }
68045
68046         // implied layer tag..
68047         if (this.tags.location === 'overground') return 1;
68048         if (this.tags.location === 'underground') return -1;
68049         if (this.tags.location === 'underwater') return -10;
68050
68051         if (this.tags.power === 'line') return 10;
68052         if (this.tags.power === 'minor_line') return 10;
68053         if (this.tags.aerialway) return 10;
68054         if (this.tags.bridge) return 1;
68055         if (this.tags.cutting) return -1;
68056         if (this.tags.tunnel) return -1;
68057         if (this.tags.waterway) return -1;
68058         if (this.tags.man_made === 'pipeline') return -10;
68059         if (this.tags.boundary) return -10;
68060         return 0;
68061     },
68062
68063
68064     isOneWay: function() {
68065         // explicit oneway tag..
68066         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
68067         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
68068
68069         // implied oneway tag..
68070         for (var key in this.tags) {
68071             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
68072                 return true;
68073         }
68074         return false;
68075     },
68076
68077
68078     lanes: function() {
68079         return osmLanes(this);
68080     },
68081
68082
68083     isClosed: function() {
68084         return this.nodes.length > 1 && this.first() === this.last();
68085     },
68086
68087
68088     isConvex: function(resolver) {
68089         if (!this.isClosed() || this.isDegenerate()) return null;
68090
68091         var nodes = lodash.uniq(resolver.childNodes(this)),
68092             coords = lodash.map(nodes, 'loc'),
68093             curr = 0, prev = 0;
68094
68095         for (var i = 0; i < coords.length; i++) {
68096             var o = coords[(i+1) % coords.length],
68097                 a = coords[i],
68098                 b = coords[(i+2) % coords.length],
68099                 res = geoCross(o, a, b);
68100
68101             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
68102             if (curr === 0) {
68103                 continue;
68104             } else if (prev && curr !== prev) {
68105                 return false;
68106             }
68107             prev = curr;
68108         }
68109         return true;
68110     },
68111
68112
68113     isArea: function() {
68114         if (this.tags.area === 'yes')
68115             return true;
68116         if (!this.isClosed() || this.tags.area === 'no')
68117             return false;
68118         for (var key in this.tags) {
68119             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
68120                 return true;
68121             }
68122         }
68123         return false;
68124     },
68125
68126
68127     isDegenerate: function() {
68128         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
68129     },
68130
68131
68132     areAdjacent: function(n1, n2) {
68133         for (var i = 0; i < this.nodes.length; i++) {
68134             if (this.nodes[i] === n1) {
68135                 if (this.nodes[i - 1] === n2) return true;
68136                 if (this.nodes[i + 1] === n2) return true;
68137             }
68138         }
68139         return false;
68140     },
68141
68142
68143     geometry: function(graph) {
68144         return graph.transient(this, 'geometry', function() {
68145             return this.isArea() ? 'area' : 'line';
68146         });
68147     },
68148
68149
68150     // If this way is not closed, append the beginning node to the end of the nodelist to close it.
68151     close: function() {
68152         if (this.isClosed() || !this.nodes.length) return this;
68153
68154         var nodes = this.nodes.slice();
68155         nodes = nodes.filter(noRepeatNodes);
68156         nodes.push(nodes[0]);
68157         return this.update({ nodes: nodes });
68158     },
68159
68160
68161     // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
68162     unclose: function() {
68163         if (!this.isClosed()) return this;
68164
68165         var nodes = this.nodes.slice(),
68166             connector = this.first(),
68167             i = nodes.length - 1;
68168
68169         // remove trailing connectors..
68170         while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68171             nodes.splice(i, 1);
68172             i = nodes.length - 1;
68173         }
68174
68175         nodes = nodes.filter(noRepeatNodes);
68176         return this.update({ nodes: nodes });
68177     },
68178
68179
68180     // Adds a node (id) in front of the node which is currently at position index.
68181     // If index is undefined, the node will be added to the end of the way for linear ways,
68182     //   or just before the final connecting node for circular ways.
68183     // Consecutive duplicates are eliminated including existing ones.
68184     // Circularity is always preserved when adding a node.
68185     addNode: function(id, index) {
68186         var nodes = this.nodes.slice(),
68187             isClosed = this.isClosed(),
68188             max$$1 = isClosed ? nodes.length - 1 : nodes.length;
68189
68190         if (index === undefined) {
68191             index = max$$1;
68192         }
68193
68194         if (index < 0 || index > max$$1) {
68195             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68196         }
68197
68198         // If this is a closed way, remove all connector nodes except the first one
68199         // (there may be duplicates) and adjust index if necessary..
68200         if (isClosed) {
68201             var connector = this.first();
68202
68203             // leading connectors..
68204             var i = 1;
68205             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68206                 nodes.splice(i, 1);
68207                 if (index > i) index--;
68208             }
68209
68210             // trailing connectors..
68211             i = nodes.length - 1;
68212             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68213                 nodes.splice(i, 1);
68214                 if (index > i) index--;
68215                 i = nodes.length - 1;
68216             }
68217         }
68218
68219         nodes.splice(index, 0, id);
68220         nodes = nodes.filter(noRepeatNodes);
68221
68222         // If the way was closed before, append a connector node to keep it closed..
68223         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68224             nodes.push(nodes[0]);
68225         }
68226
68227         return this.update({ nodes: nodes });
68228     },
68229
68230
68231     // Replaces the node which is currently at position index with the given node (id).
68232     // Consecutive duplicates are eliminated including existing ones.
68233     // Circularity is preserved when updating a node.
68234     updateNode: function(id, index) {
68235         var nodes = this.nodes.slice(),
68236             isClosed = this.isClosed(),
68237             max$$1 = nodes.length - 1;
68238
68239         if (index === undefined || index < 0 || index > max$$1) {
68240             throw new RangeError('index ' + index + ' out of range 0..' + max$$1);
68241         }
68242
68243         // If this is a closed way, remove all connector nodes except the first one
68244         // (there may be duplicates) and adjust index if necessary..
68245         if (isClosed) {
68246             var connector = this.first();
68247
68248             // leading connectors..
68249             var i = 1;
68250             while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
68251                 nodes.splice(i, 1);
68252                 if (index > i) index--;
68253             }
68254
68255             // trailing connectors..
68256             i = nodes.length - 1;
68257             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
68258                 nodes.splice(i, 1);
68259                 if (index === i) index = 0;  // update leading connector instead
68260                 i = nodes.length - 1;
68261             }
68262         }
68263
68264         nodes.splice(index, 1, id);
68265         nodes = nodes.filter(noRepeatNodes);
68266
68267         // If the way was closed before, append a connector node to keep it closed..
68268         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68269             nodes.push(nodes[0]);
68270         }
68271
68272         return this.update({nodes: nodes});
68273     },
68274
68275
68276     // Replaces each occurrence of node id needle with replacement.
68277     // Consecutive duplicates are eliminated including existing ones.
68278     // Circularity is preserved.
68279     replaceNode: function(needle, replacement) {
68280         var nodes = this.nodes.slice(),
68281             isClosed = this.isClosed();
68282
68283         for (var i = 0; i < nodes.length; i++) {
68284             if (nodes[i] === needle) {
68285                 nodes[i] = replacement;
68286             }
68287         }
68288
68289         nodes = nodes.filter(noRepeatNodes);
68290
68291         // If the way was closed before, append a connector node to keep it closed..
68292         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68293             nodes.push(nodes[0]);
68294         }
68295
68296         return this.update({nodes: nodes});
68297     },
68298
68299
68300     // Removes each occurrence of node id needle with replacement.
68301     // Consecutive duplicates are eliminated including existing ones.
68302     // Circularity is preserved.
68303     removeNode: function(id) {
68304         var nodes = this.nodes.slice(),
68305             isClosed = this.isClosed();
68306
68307         nodes = nodes
68308             .filter(function(node) { return node !== id; })
68309             .filter(noRepeatNodes);
68310
68311         // If the way was closed before, append a connector node to keep it closed..
68312         if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
68313             nodes.push(nodes[0]);
68314         }
68315
68316         return this.update({nodes: nodes});
68317     },
68318
68319
68320     asJXON: function(changeset_id) {
68321         var r = {
68322             way: {
68323                 '@id': this.osmId(),
68324                 '@version': this.version || 0,
68325                 nd: lodash.map(this.nodes, function(id) {
68326                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
68327                 }),
68328                 tag: lodash.map(this.tags, function(v, k) {
68329                     return { keyAttributes: { k: k, v: v } };
68330                 })
68331             }
68332         };
68333         if (changeset_id) {
68334             r.way['@changeset'] = changeset_id;
68335         }
68336         return r;
68337     },
68338
68339
68340     asGeoJSON: function(resolver) {
68341         return resolver.transient(this, 'GeoJSON', function() {
68342             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
68343             if (this.isArea() && this.isClosed()) {
68344                 return {
68345                     type: 'Polygon',
68346                     coordinates: [coordinates]
68347                 };
68348             } else {
68349                 return {
68350                     type: 'LineString',
68351                     coordinates: coordinates
68352                 };
68353             }
68354         });
68355     },
68356
68357
68358     area: function(resolver) {
68359         return resolver.transient(this, 'area', function() {
68360             var nodes = resolver.childNodes(this);
68361
68362             var json$$1 = {
68363                 type: 'Polygon',
68364                 coordinates: [lodash.map(nodes, 'loc')]
68365             };
68366
68367             if (!this.isClosed() && nodes.length) {
68368                 json$$1.coordinates[0].push(nodes[0].loc);
68369             }
68370
68371             var area$$1 = area(json$$1);
68372
68373             // Heuristic for detecting counterclockwise winding order. Assumes
68374             // that OpenStreetMap polygons are not hemisphere-spanning.
68375             if (area$$1 > 2 * Math.PI) {
68376                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
68377                 area$$1 = area(json$$1);
68378             }
68379
68380             return isNaN(area$$1) ? 0 : area$$1;
68381         });
68382     }
68383 });
68384
68385
68386 // Filter function to eliminate consecutive duplicates.
68387 function noRepeatNodes(node, i, arr) {
68388     return i === 0 || node !== arr[i - 1];
68389 }
68390
68391 function osmTurn(turn) {
68392     if (!(this instanceof osmTurn))
68393         return new osmTurn(turn);
68394     lodash.extend(this, turn);
68395 }
68396
68397
68398 function osmIntersection(graph, vertexId) {
68399     var vertex = graph.entity(vertexId),
68400         parentWays = graph.parentWays(vertex),
68401         coincident = [],
68402         highways = {};
68403
68404     function addHighway(way, adjacentNodeId) {
68405         if (highways[adjacentNodeId]) {
68406             coincident.push(adjacentNodeId);
68407         } else {
68408             highways[adjacentNodeId] = way;
68409         }
68410     }
68411
68412     // Pre-split ways that would need to be split in
68413     // order to add a restriction. The real split will
68414     // happen when the restriction is added.
68415     parentWays.forEach(function(way) {
68416         if (!way.tags.highway || way.isArea() || way.isDegenerate())
68417             return;
68418
68419         var isFirst = (vertexId === way.first()),
68420             isLast = (vertexId === way.last()),
68421             isAffix = (isFirst || isLast),
68422             isClosingNode = (isFirst && isLast);
68423
68424         if (isAffix && !isClosingNode) {
68425             var index = (isFirst ? 1 : way.nodes.length - 2);
68426             addHighway(way, way.nodes[index]);
68427
68428         } else {
68429             var splitIndex, wayA, wayB, indexA, indexB;
68430             if (isClosingNode) {
68431                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
68432                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
68433                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68434                 indexA = 1;
68435                 indexB = way.nodes.length - 2;
68436             } else {
68437                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
68438                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
68439                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
68440                 indexA = splitIndex - 1;
68441                 indexB = splitIndex + 1;
68442             }
68443             graph = graph.replace(wayA).replace(wayB);
68444             addHighway(wayA, way.nodes[indexA]);
68445             addHighway(wayB, way.nodes[indexB]);
68446         }
68447     });
68448
68449     // remove any ways from this intersection that are coincident
68450     // (i.e. any adjacent node used by more than one intersecting way)
68451     coincident.forEach(function (n) {
68452         delete highways[n];
68453     });
68454
68455
68456     var intersection = {
68457         highways: highways,
68458         ways: lodash.values(highways),
68459         graph: graph
68460     };
68461
68462
68463     intersection.adjacentNodeId = function(fromWayId) {
68464         return lodash.find(lodash.keys(highways), function(k) {
68465             return highways[k].id === fromWayId;
68466         });
68467     };
68468
68469
68470     intersection.turns = function(fromNodeId) {
68471         var start = highways[fromNodeId];
68472         if (!start)
68473             return [];
68474
68475         if (start.first() === vertex.id && start.tags.oneway === 'yes')
68476             return [];
68477         if (start.last() === vertex.id && start.tags.oneway === '-1')
68478             return [];
68479
68480         function withRestriction(turn) {
68481             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
68482                 if (relation.tags.type !== 'restriction')
68483                     return;
68484
68485                 var f = relation.memberByRole('from'),
68486                     t = relation.memberByRole('to'),
68487                     v = relation.memberByRole('via');
68488
68489                 if (f && f.id === turn.from.way &&
68490                     v && v.id === turn.via.node &&
68491                     t && t.id === turn.to.way) {
68492                     turn.restriction = relation.id;
68493                 } else if (/^only_/.test(relation.tags.restriction) &&
68494                     f && f.id === turn.from.way &&
68495                     v && v.id === turn.via.node &&
68496                     t && t.id !== turn.to.way) {
68497                     turn.restriction = relation.id;
68498                     turn.indirect_restriction = true;
68499                 }
68500             });
68501
68502             return osmTurn(turn);
68503         }
68504
68505
68506         var from = {
68507                 node: fromNodeId,
68508                 way: start.id.split(/-(a|b)/)[0]
68509             },
68510             via = { node: vertex.id },
68511             turns = [];
68512
68513         lodash.each(highways, function(end, adjacentNodeId) {
68514             if (end === start)
68515                 return;
68516
68517             // backward
68518             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
68519                 turns.push(withRestriction({
68520                     from: from,
68521                     via: via,
68522                     to: {
68523                         node: adjacentNodeId,
68524                         way: end.id.split(/-(a|b)/)[0]
68525                     }
68526                 }));
68527             }
68528
68529             // forward
68530             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
68531                 turns.push(withRestriction({
68532                     from: from,
68533                     via: via,
68534                     to: {
68535                         node: adjacentNodeId,
68536                         way: end.id.split(/-(a|b)/)[0]
68537                     }
68538                 }));
68539             }
68540
68541         });
68542
68543         // U-turn
68544         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
68545             turns.push(withRestriction({
68546                 from: from,
68547                 via: via,
68548                 to: from,
68549                 u: true
68550             }));
68551         }
68552
68553         return turns;
68554     };
68555
68556     return intersection;
68557 }
68558
68559
68560 function osmInferRestriction(graph, from, via, to, projection) {
68561     var fromWay = graph.entity(from.way),
68562         fromNode = graph.entity(from.node),
68563         toWay = graph.entity(to.way),
68564         toNode = graph.entity(to.node),
68565         viaNode = graph.entity(via.node),
68566         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
68567             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
68568         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
68569             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
68570         angle = geoAngle(viaNode, fromNode, projection) -
68571                 geoAngle(viaNode, toNode, projection);
68572
68573     angle = angle * 180 / Math.PI;
68574
68575     while (angle < 0)
68576         angle += 360;
68577
68578     if (fromNode === toNode)
68579         return 'no_u_turn';
68580     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
68581         return 'no_u_turn';
68582     if (angle < 158)
68583         return 'no_right_turn';
68584     if (angle > 202)
68585         return 'no_left_turn';
68586
68587     return 'no_straight_on';
68588 }
68589
68590 function actionAddMember(relationId, member, memberIndex) {
68591     return function(graph) {
68592         var relation = graph.entity(relationId);
68593
68594         if (isNaN(memberIndex) && member.type === 'way') {
68595             var members = relation.indexedMembers();
68596             members.push(member);
68597
68598             var joined = osmJoinWays(members, graph);
68599             for (var i = 0; i < joined.length; i++) {
68600                 var segment = joined[i];
68601                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
68602                     if (segment[j] !== member)
68603                         continue;
68604
68605                     if (j === 0) {
68606                         memberIndex = segment[j + 1].index;
68607                     } else if (j === segment.length - 1) {
68608                         memberIndex = segment[j - 1].index + 1;
68609                     } else {
68610                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
68611                     }
68612                 }
68613             }
68614         }
68615
68616         return graph.replace(relation.addMember(member, memberIndex));
68617     };
68618 }
68619
68620 function actionAddMidpoint(midpoint, node) {
68621     return function(graph) {
68622         graph = graph.replace(node.move(midpoint.loc));
68623
68624         var parents = lodash.intersection(
68625             graph.parentWays(graph.entity(midpoint.edge[0])),
68626             graph.parentWays(graph.entity(midpoint.edge[1])));
68627
68628         parents.forEach(function(way) {
68629             for (var i = 0; i < way.nodes.length - 1; i++) {
68630                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
68631                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
68632
68633                     // Add only one midpoint on doubled-back segments,
68634                     // turning them into self-intersections.
68635                     return;
68636                 }
68637             }
68638         });
68639
68640         return graph;
68641     };
68642 }
68643
68644 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
68645 function actionAddVertex(wayId, nodeId, index) {
68646     return function(graph) {
68647         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
68648     };
68649 }
68650
68651 function actionChangeMember(relationId, member, memberIndex) {
68652     return function(graph) {
68653         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
68654     };
68655 }
68656
68657 function actionChangePreset(entityId, oldPreset, newPreset) {
68658     return function(graph) {
68659         var entity = graph.entity(entityId),
68660             geometry = entity.geometry(graph),
68661             tags = entity.tags;
68662
68663         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
68664         if (newPreset) tags = newPreset.applyTags(tags, geometry);
68665
68666         return graph.replace(entity.update({tags: tags}));
68667     };
68668 }
68669
68670 function actionChangeTags(entityId, tags) {
68671     return function(graph) {
68672         var entity = graph.entity(entityId);
68673         return graph.replace(entity.update({tags: tags}));
68674     };
68675 }
68676
68677 function actionCircularize(wayId, projection, maxAngle) {
68678     maxAngle = (maxAngle || 20) * Math.PI / 180;
68679
68680
68681     var action = function(graph, t) {
68682         if (t === null || !isFinite(t)) t = 1;
68683         t = Math.min(Math.max(+t, 0), 1);
68684
68685         var way = graph.entity(wayId),
68686             origNodes = {};
68687
68688         graph.childNodes(way).forEach(function(node) {
68689             if (!origNodes[node.id]) origNodes[node.id] = node;
68690         });
68691
68692         if (!way.isConvex(graph)) {
68693             graph = action.makeConvex(graph);
68694         }
68695
68696         var nodes = lodash.uniq(graph.childNodes(way)),
68697             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
68698             points = nodes.map(function(n) { return projection(n.loc); }),
68699             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
68700             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
68701             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
68702             sign = d3polygonArea(points) > 0 ? 1 : -1,
68703             ids;
68704
68705         // we need atleast two key nodes for the algorithm to work
68706         if (!keyNodes.length) {
68707             keyNodes = [nodes[0]];
68708             keyPoints = [points[0]];
68709         }
68710
68711         if (keyNodes.length === 1) {
68712             var index = nodes.indexOf(keyNodes[0]),
68713                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
68714
68715             keyNodes.push(nodes[oppositeIndex]);
68716             keyPoints.push(points[oppositeIndex]);
68717         }
68718
68719         // key points and nodes are those connected to the ways,
68720         // they are projected onto the circle, inbetween nodes are moved
68721         // to constant intervals between key nodes, extra inbetween nodes are
68722         // added if necessary.
68723         for (var i = 0; i < keyPoints.length; i++) {
68724             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
68725                 startNode = keyNodes[i],
68726                 endNode = keyNodes[nextKeyNodeIndex],
68727                 startNodeIndex = nodes.indexOf(startNode),
68728                 endNodeIndex = nodes.indexOf(endNode),
68729                 numberNewPoints = -1,
68730                 indexRange = endNodeIndex - startNodeIndex,
68731                 nearNodes = {},
68732                 inBetweenNodes = [],
68733                 startAngle, endAngle, totalAngle, eachAngle,
68734                 angle, loc, node, origNode, j;
68735
68736             if (indexRange < 0) {
68737                 indexRange += nodes.length;
68738             }
68739
68740             // position this key node
68741             var distance = geoEuclideanDistance(centroid, keyPoints[i]);
68742             if (distance === 0) { distance = 1e-4; }
68743             keyPoints[i] = [
68744                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
68745                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius
68746             ];
68747             loc = projection.invert(keyPoints[i]);
68748             node = keyNodes[i];
68749             origNode = origNodes[node.id];
68750             node = node.move(geoInterp(origNode.loc, loc, t));
68751             graph = graph.replace(node);
68752
68753             // figure out the between delta angle we want to match to
68754             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
68755             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
68756             totalAngle = endAngle - startAngle;
68757
68758             // detects looping around -pi/pi
68759             if (totalAngle * sign > 0) {
68760                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
68761             }
68762
68763             do {
68764                 numberNewPoints++;
68765                 eachAngle = totalAngle / (indexRange + numberNewPoints);
68766             } while (Math.abs(eachAngle) > maxAngle);
68767
68768
68769             // move existing nodes
68770             for (j = 1; j < indexRange; j++) {
68771                 angle = startAngle + j * eachAngle;
68772                 loc = projection.invert([
68773                     centroid[0] + Math.cos(angle) * radius,
68774                     centroid[1] + Math.sin(angle) * radius
68775                 ]);
68776
68777                 node = nodes[(j + startNodeIndex) % nodes.length];
68778                 origNode = origNodes[node.id];
68779                 nearNodes[node.id] = angle;
68780
68781                 node = node.move(geoInterp(origNode.loc, loc, t));
68782                 graph = graph.replace(node);
68783             }
68784
68785             // add new inbetween nodes if necessary
68786             for (j = 0; j < numberNewPoints; j++) {
68787                 angle = startAngle + (indexRange + j) * eachAngle;
68788                 loc = projection.invert([
68789                     centroid[0] + Math.cos(angle) * radius,
68790                     centroid[1] + Math.sin(angle) * radius
68791                 ]);
68792
68793                 // choose a nearnode to use as the original
68794                 var min$$1 = Infinity;
68795                 for (var nodeId in nearNodes) {
68796                     var nearAngle = nearNodes[nodeId],
68797                         dist = Math.abs(nearAngle - angle);
68798                     if (dist < min$$1) {
68799                         dist = min$$1;
68800                         origNode = origNodes[nodeId];
68801                     }
68802                 }
68803
68804                 node = osmNode({ loc: geoInterp(origNode.loc, loc, t) });
68805                 graph = graph.replace(node);
68806
68807                 nodes.splice(endNodeIndex + j, 0, node);
68808                 inBetweenNodes.push(node.id);
68809             }
68810
68811             // Check for other ways that share these keyNodes..
68812             // If keyNodes are adjacent in both ways,
68813             // we can add inBetween nodes to that shared way too..
68814             if (indexRange === 1 && inBetweenNodes.length) {
68815                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
68816                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
68817                     wayDirection1 = (endIndex1 - startIndex1);
68818                 if (wayDirection1 < -1) { wayDirection1 = 1; }
68819
68820                 /* eslint-disable no-loop-func */
68821                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
68822                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
68823                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
68824                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
68825                             wayDirection2 = (endIndex2 - startIndex2),
68826                             insertAt = endIndex2;
68827                         if (wayDirection2 < -1) { wayDirection2 = 1; }
68828
68829                         if (wayDirection1 !== wayDirection2) {
68830                             inBetweenNodes.reverse();
68831                             insertAt = startIndex2;
68832                         }
68833                         for (j = 0; j < inBetweenNodes.length; j++) {
68834                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
68835                         }
68836                         graph = graph.replace(sharedWay);
68837                     }
68838                 });
68839                 /* eslint-enable no-loop-func */
68840             }
68841
68842         }
68843
68844         // update the way to have all the new nodes
68845         ids = nodes.map(function(n) { return n.id; });
68846         ids.push(ids[0]);
68847
68848         way = way.update({nodes: ids});
68849         graph = graph.replace(way);
68850
68851         return graph;
68852     };
68853
68854
68855     action.makeConvex = function(graph) {
68856         var way = graph.entity(wayId),
68857             nodes = lodash.uniq(graph.childNodes(way)),
68858             points = nodes.map(function(n) { return projection(n.loc); }),
68859             sign = d3polygonArea(points) > 0 ? 1 : -1,
68860             hull = d3polygonHull(points);
68861
68862         // D3 convex hulls go counterclockwise..
68863         if (sign === -1) {
68864             nodes.reverse();
68865             points.reverse();
68866         }
68867
68868         for (var i = 0; i < hull.length - 1; i++) {
68869             var startIndex = points.indexOf(hull[i]),
68870                 endIndex = points.indexOf(hull[i+1]),
68871                 indexRange = (endIndex - startIndex);
68872
68873             if (indexRange < 0) {
68874                 indexRange += nodes.length;
68875             }
68876
68877             // move interior nodes to the surface of the convex hull..
68878             for (var j = 1; j < indexRange; j++) {
68879                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
68880                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
68881                 graph = graph.replace(node);
68882             }
68883         }
68884         return graph;
68885     };
68886
68887
68888     action.disabled = function(graph) {
68889         if (!graph.entity(wayId).isClosed())
68890             return 'not_closed';
68891     };
68892
68893
68894     action.transitionable = true;
68895
68896
68897     return action;
68898 }
68899
68900 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
68901 function actionDeleteWay(wayId) {
68902
68903
68904     function canDeleteNode(node, graph) {
68905         return !graph.parentWays(node).length &&
68906             !graph.parentRelations(node).length &&
68907             !node.hasInterestingTags();
68908     }
68909
68910
68911     var action = function(graph) {
68912         var way = graph.entity(wayId);
68913
68914         graph.parentRelations(way)
68915             .forEach(function(parent) {
68916                 parent = parent.removeMembersWithID(wayId);
68917                 graph = graph.replace(parent);
68918
68919                 if (parent.isDegenerate()) {
68920                     graph = actionDeleteRelation(parent.id)(graph);
68921                 }
68922             });
68923
68924         lodash.uniq(way.nodes).forEach(function(nodeId) {
68925             graph = graph.replace(way.removeNode(nodeId));
68926
68927             var node = graph.entity(nodeId);
68928             if (canDeleteNode(node, graph)) {
68929                 graph = graph.remove(node);
68930             }
68931         });
68932
68933         return graph.remove(way);
68934     };
68935
68936
68937     return action;
68938 }
68939
68940 function actionDeleteMultiple(ids) {
68941     var actions = {
68942         way: actionDeleteWay,
68943         node: actionDeleteNode,
68944         relation: actionDeleteRelation
68945     };
68946
68947
68948     var action = function(graph) {
68949         ids.forEach(function(id) {
68950             if (graph.hasEntity(id)) { // It may have been deleted aready.
68951                 graph = actions[graph.entity(id).type](id)(graph);
68952             }
68953         });
68954
68955         return graph;
68956     };
68957
68958
68959     return action;
68960 }
68961
68962 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
68963 function actionDeleteRelation(relationId) {
68964
68965
68966     function canDeleteEntity(entity, graph) {
68967         return !graph.parentWays(entity).length &&
68968             !graph.parentRelations(entity).length &&
68969             !entity.hasInterestingTags();
68970     }
68971
68972
68973     var action = function(graph) {
68974         var relation = graph.entity(relationId);
68975
68976         graph.parentRelations(relation)
68977             .forEach(function(parent) {
68978                 parent = parent.removeMembersWithID(relationId);
68979                 graph = graph.replace(parent);
68980
68981                 if (parent.isDegenerate()) {
68982                     graph = actionDeleteRelation(parent.id)(graph);
68983                 }
68984             });
68985
68986         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
68987             graph = graph.replace(relation.removeMembersWithID(memberId));
68988
68989             var entity = graph.entity(memberId);
68990             if (canDeleteEntity(entity, graph)) {
68991                 graph = actionDeleteMultiple([memberId])(graph);
68992             }
68993         });
68994
68995         return graph.remove(relation);
68996     };
68997
68998
68999     return action;
69000 }
69001
69002 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
69003 function actionDeleteNode(nodeId) {
69004     var action = function(graph) {
69005         var node = graph.entity(nodeId);
69006
69007         graph.parentWays(node)
69008             .forEach(function(parent) {
69009                 parent = parent.removeNode(nodeId);
69010                 graph = graph.replace(parent);
69011
69012                 if (parent.isDegenerate()) {
69013                     graph = actionDeleteWay(parent.id)(graph);
69014                 }
69015             });
69016
69017         graph.parentRelations(node)
69018             .forEach(function(parent) {
69019                 parent = parent.removeMembersWithID(nodeId);
69020                 graph = graph.replace(parent);
69021
69022                 if (parent.isDegenerate()) {
69023                     graph = actionDeleteRelation(parent.id)(graph);
69024                 }
69025             });
69026
69027         return graph.remove(node);
69028     };
69029
69030
69031     return action;
69032 }
69033
69034 // Connect the ways at the given nodes.
69035 //
69036 // The last node will survive. All other nodes will be replaced with
69037 // the surviving node in parent ways, and then removed.
69038 //
69039 // Tags and relation memberships of of non-surviving nodes are merged
69040 // to the survivor.
69041 //
69042 // This is the inverse of `iD.actionDisconnect`.
69043 //
69044 // Reference:
69045 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
69046 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
69047 //
69048 function actionConnect(nodeIds) {
69049     return function(graph) {
69050         var survivor = graph.entity(lodash.last(nodeIds));
69051
69052         for (var i = 0; i < nodeIds.length - 1; i++) {
69053             var node = graph.entity(nodeIds[i]);
69054
69055             /* eslint-disable no-loop-func */
69056             graph.parentWays(node).forEach(function(parent) {
69057                 if (!parent.areAdjacent(node.id, survivor.id)) {
69058                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
69059                 }
69060             });
69061
69062             graph.parentRelations(node).forEach(function(parent) {
69063                 graph = graph.replace(parent.replaceMember(node, survivor));
69064             });
69065             /* eslint-enable no-loop-func */
69066
69067             survivor = survivor.mergeTags(node.tags);
69068             graph = actionDeleteNode(node.id)(graph);
69069         }
69070
69071         graph = graph.replace(survivor);
69072
69073         return graph;
69074     };
69075 }
69076
69077 function actionCopyEntities(ids, fromGraph) {
69078     var copies = {};
69079
69080
69081     var action = function(graph) {
69082         ids.forEach(function(id) {
69083             fromGraph.entity(id).copy(fromGraph, copies);
69084         });
69085
69086         for (var id in copies) {
69087             graph = graph.replace(copies[id]);
69088         }
69089
69090         return graph;
69091     };
69092
69093
69094     action.copies = function() {
69095         return copies;
69096     };
69097
69098
69099     return action;
69100 }
69101
69102 function actionDeleteMember(relationId, memberIndex) {
69103     return function(graph) {
69104         var relation = graph.entity(relationId)
69105             .removeMember(memberIndex);
69106
69107         graph = graph.replace(relation);
69108
69109         if (relation.isDegenerate())
69110             graph = actionDeleteRelation(relation.id)(graph);
69111
69112         return graph;
69113     };
69114 }
69115
69116 function actionDeprecateTags(entityId) {
69117
69118     return function(graph) {
69119         var entity = graph.entity(entityId),
69120             newtags = lodash.clone(entity.tags),
69121             change = false,
69122             rule;
69123
69124         // This handles dataDeprecated tags with a single condition
69125         for (var i = 0; i < dataDeprecated.length; i++) {
69126
69127             rule = dataDeprecated[i];
69128             var match = lodash.toPairs(rule.old)[0],
69129                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
69130
69131             if (entity.tags[match[0]] && match[1] === '*') {
69132
69133                 var value = entity.tags[match[0]];
69134                 if (replacements && !newtags[replacements[0][0]]) {
69135                     newtags[replacements[0][0]] = value;
69136                 }
69137                 delete newtags[match[0]];
69138                 change = true;
69139
69140             } else if (entity.tags[match[0]] === match[1]) {
69141                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
69142                 change = true;
69143             }
69144         }
69145
69146         if (change) {
69147             return graph.replace(entity.update({tags: newtags}));
69148         } else {
69149             return graph;
69150         }
69151     };
69152 }
69153
69154 function actionDiscardTags(difference) {
69155
69156     return function(graph) {
69157         function discardTags(entity) {
69158             if (!lodash.isEmpty(entity.tags)) {
69159                 var tags = {};
69160                 lodash.each(entity.tags, function(v, k) {
69161                     if (v) tags[k] = v;
69162                 });
69163
69164                 graph = graph.replace(entity.update({
69165                     tags: lodash.omit(tags, dataDiscarded)
69166                 }));
69167             }
69168         }
69169
69170         difference.modified().forEach(discardTags);
69171         difference.created().forEach(discardTags);
69172
69173         return graph;
69174     };
69175 }
69176
69177 // Disconect the ways at the given node.
69178 //
69179 // Optionally, disconnect only the given ways.
69180 //
69181 // For testing convenience, accepts an ID to assign to the (first) new node.
69182 // Normally, this will be undefined and the way will automatically
69183 // be assigned a new ID.
69184 //
69185 // This is the inverse of `iD.actionConnect`.
69186 //
69187 // Reference:
69188 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
69189 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
69190 //
69191 function actionDisconnect(nodeId, newNodeId) {
69192     var wayIds;
69193
69194
69195     var action = function(graph) {
69196         var node = graph.entity(nodeId),
69197             connections = action.connections(graph);
69198
69199         connections.forEach(function(connection) {
69200             var way = graph.entity(connection.wayID),
69201                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
69202
69203             graph = graph.replace(newNode);
69204             if (connection.index === 0 && way.isArea()) {
69205                 // replace shared node with shared node..
69206                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
69207             } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
69208                 // replace closing node with new new node..
69209                 graph = graph.replace(way.unclose().addNode(newNode.id));
69210             } else {
69211                 // replace shared node with multiple new nodes..
69212                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
69213             }
69214         });
69215
69216         return graph;
69217     };
69218
69219
69220     action.connections = function(graph) {
69221         var candidates = [],
69222             keeping = false,
69223             parentWays = graph.parentWays(graph.entity(nodeId));
69224
69225         parentWays.forEach(function(way) {
69226             if (wayIds && wayIds.indexOf(way.id) === -1) {
69227                 keeping = true;
69228                 return;
69229             }
69230             if (way.isArea() && (way.nodes[0] === nodeId)) {
69231                 candidates.push({ wayID: way.id, index: 0 });
69232             } else {
69233                 way.nodes.forEach(function(waynode, index) {
69234                     if (waynode === nodeId) {
69235                         candidates.push({ wayID: way.id, index: index });
69236                     }
69237                 });
69238             }
69239         });
69240
69241         return keeping ? candidates : candidates.slice(1);
69242     };
69243
69244
69245     action.disabled = function(graph) {
69246         var connections = action.connections(graph);
69247         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
69248             return 'not_connected';
69249
69250         var parentWays = graph.parentWays(graph.entity(nodeId)),
69251             seenRelationIds = {},
69252             sharedRelation;
69253
69254         parentWays.forEach(function(way) {
69255             if (wayIds && wayIds.indexOf(way.id) === -1)
69256                 return;
69257
69258             var relations = graph.parentRelations(way);
69259             relations.forEach(function(relation) {
69260                 if (relation.id in seenRelationIds) {
69261                     sharedRelation = relation;
69262                 } else {
69263                     seenRelationIds[relation.id] = true;
69264                 }
69265             });
69266         });
69267
69268         if (sharedRelation)
69269             return 'relation';
69270     };
69271
69272
69273     action.limitWays = function(_) {
69274         if (!arguments.length) return wayIds;
69275         wayIds = _;
69276         return action;
69277     };
69278
69279
69280     return action;
69281 }
69282
69283 // Join ways at the end node they share.
69284 //
69285 // This is the inverse of `iD.actionSplit`.
69286 //
69287 // Reference:
69288 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
69289 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
69290 //
69291 function actionJoin(ids) {
69292
69293     function groupEntitiesByGeometry(graph) {
69294         var entities = ids.map(function(id) { return graph.entity(id); });
69295         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69296     }
69297
69298
69299     var action = function(graph) {
69300         var ways = ids.map(graph.entity, graph),
69301             survivor = ways[0];
69302
69303         // Prefer to keep an existing way.
69304         for (var i = 0; i < ways.length; i++) {
69305             if (!ways[i].isNew()) {
69306                 survivor = ways[i];
69307                 break;
69308             }
69309         }
69310
69311         var joined = osmJoinWays(ways, graph)[0];
69312
69313         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
69314         graph = graph.replace(survivor);
69315
69316         joined.forEach(function(way) {
69317             if (way.id === survivor.id)
69318                 return;
69319
69320             graph.parentRelations(way).forEach(function(parent) {
69321                 graph = graph.replace(parent.replaceMember(way, survivor));
69322             });
69323
69324             survivor = survivor.mergeTags(way.tags);
69325
69326             graph = graph.replace(survivor);
69327             graph = actionDeleteWay(way.id)(graph);
69328         });
69329
69330         return graph;
69331     };
69332
69333
69334     action.disabled = function(graph) {
69335         var geometries = groupEntitiesByGeometry(graph);
69336         if (ids.length < 2 || ids.length !== geometries.line.length)
69337             return 'not_eligible';
69338
69339         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
69340         if (joined.length > 1)
69341             return 'not_adjacent';
69342
69343         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
69344             relation,
69345             tags = {},
69346             conflicting = false;
69347
69348         joined[0].forEach(function(way) {
69349             var parents = graph.parentRelations(way);
69350             parents.forEach(function(parent) {
69351                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
69352                     relation = parent;
69353             });
69354
69355             for (var k in way.tags) {
69356                 if (!(k in tags)) {
69357                     tags[k] = way.tags[k];
69358                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
69359                     conflicting = true;
69360                 }
69361             }
69362         });
69363
69364         if (relation)
69365             return 'restriction';
69366
69367         if (conflicting)
69368             return 'conflicting_tags';
69369     };
69370
69371
69372     return action;
69373 }
69374
69375 function actionMerge(ids) {
69376
69377     function groupEntitiesByGeometry(graph) {
69378         var entities = ids.map(function(id) { return graph.entity(id); });
69379         return lodash.extend({point: [], area: [], line: [], relation: []},
69380             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
69381     }
69382
69383
69384     var action = function(graph) {
69385         var geometries = groupEntitiesByGeometry(graph),
69386             target = geometries.area[0] || geometries.line[0],
69387             points = geometries.point;
69388
69389         points.forEach(function(point) {
69390             target = target.mergeTags(point.tags);
69391             graph = graph.replace(target);
69392
69393             graph.parentRelations(point).forEach(function(parent) {
69394                 graph = graph.replace(parent.replaceMember(point, target));
69395             });
69396
69397             var nodes = lodash.uniq(graph.childNodes(target)),
69398                 removeNode = point;
69399
69400             for (var i = 0; i < nodes.length; i++) {
69401                 var node = nodes[i];
69402                 if (graph.parentWays(node).length > 1 ||
69403                     graph.parentRelations(node).length ||
69404                     node.hasInterestingTags()) {
69405                     continue;
69406                 }
69407
69408                 // Found an uninteresting child node on the target way.
69409                 // Move orig point into its place to preserve point's history. #3683
69410                 graph = graph.replace(point.update({ tags: {}, loc: node.loc }));
69411                 target = target.replaceNode(node.id, point.id);
69412                 graph = graph.replace(target);
69413                 removeNode = node;
69414                 break;
69415             }
69416
69417             graph = graph.remove(removeNode);
69418         });
69419
69420         return graph;
69421     };
69422
69423
69424     action.disabled = function(graph) {
69425         var geometries = groupEntitiesByGeometry(graph);
69426         if (geometries.point.length === 0 ||
69427             (geometries.area.length + geometries.line.length) !== 1 ||
69428             geometries.relation.length !== 0)
69429             return 'not_eligible';
69430     };
69431
69432
69433     return action;
69434 }
69435
69436 function actionMergePolygon(ids, newRelationId) {
69437
69438     function groupEntities(graph) {
69439         var entities = ids.map(function (id) { return graph.entity(id); });
69440         return lodash.extend({
69441                 closedWay: [],
69442                 multipolygon: [],
69443                 other: []
69444             }, lodash.groupBy(entities, function(entity) {
69445                 if (entity.type === 'way' && entity.isClosed()) {
69446                     return 'closedWay';
69447                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
69448                     return 'multipolygon';
69449                 } else {
69450                     return 'other';
69451                 }
69452             }));
69453     }
69454
69455
69456     var action = function(graph) {
69457         var entities = groupEntities(graph);
69458
69459         // An array representing all the polygons that are part of the multipolygon.
69460         //
69461         // Each element is itself an array of objects with an id property, and has a
69462         // locs property which is an array of the locations forming the polygon.
69463         var polygons = entities.multipolygon.reduce(function(polygons, m) {
69464             return polygons.concat(osmJoinWays(m.members, graph));
69465         }, []).concat(entities.closedWay.map(function(d) {
69466             var member = [{id: d.id}];
69467             member.nodes = graph.childNodes(d);
69468             return member;
69469         }));
69470
69471         // contained is an array of arrays of boolean values,
69472         // where contained[j][k] is true iff the jth way is
69473         // contained by the kth way.
69474         var contained = polygons.map(function(w, i) {
69475             return polygons.map(function(d, n) {
69476                 if (i === n) return null;
69477                 return geoPolygonContainsPolygon(
69478                     lodash.map(d.nodes, 'loc'),
69479                     lodash.map(w.nodes, 'loc'));
69480             });
69481         });
69482
69483         // Sort all polygons as either outer or inner ways
69484         var members = [],
69485             outer = true;
69486
69487         while (polygons.length) {
69488             extractUncontained(polygons);
69489             polygons = polygons.filter(isContained);
69490             contained = contained.filter(isContained).map(filterContained);
69491         }
69492
69493         function isContained(d, i) {
69494             return lodash.some(contained[i]);
69495         }
69496
69497         function filterContained(d) {
69498             return d.filter(isContained);
69499         }
69500
69501         function extractUncontained(polygons) {
69502             polygons.forEach(function(d, i) {
69503                 if (!isContained(d, i)) {
69504                     d.forEach(function(member) {
69505                         members.push({
69506                             type: 'way',
69507                             id: member.id,
69508                             role: outer ? 'outer' : 'inner'
69509                         });
69510                     });
69511                 }
69512             });
69513             outer = !outer;
69514         }
69515
69516         // Move all tags to one relation
69517         var relation = entities.multipolygon[0] ||
69518             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
69519
69520         entities.multipolygon.slice(1).forEach(function(m) {
69521             relation = relation.mergeTags(m.tags);
69522             graph = graph.remove(m);
69523         });
69524
69525         entities.closedWay.forEach(function(way) {
69526             function isThisOuter(m) {
69527                 return m.id === way.id && m.role !== 'inner';
69528             }
69529             if (members.some(isThisOuter)) {
69530                 relation = relation.mergeTags(way.tags);
69531                 graph = graph.replace(way.update({ tags: {} }));
69532             }
69533         });
69534
69535         return graph.replace(relation.update({
69536             members: members,
69537             tags: lodash.omit(relation.tags, 'area')
69538         }));
69539     };
69540
69541
69542     action.disabled = function(graph) {
69543         var entities = groupEntities(graph);
69544         if (entities.other.length > 0 ||
69545             entities.closedWay.length + entities.multipolygon.length < 2)
69546             return 'not_eligible';
69547         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
69548             return 'incomplete_relation';
69549     };
69550
69551
69552     return action;
69553 }
69554
69555 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
69556 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
69557 //
69558 // Permission is hereby granted, free of charge, to any person
69559 // obtaining a copy of this software and associated documentation files
69560 // (the "Software"), to deal in the Software without restriction,
69561 // including without limitation the rights to use, copy, modify, merge,
69562 // publish, distribute, sublicense, and/or sell copies of the Software,
69563 // and to permit persons to whom the Software is furnished to do so,
69564 // subject to the following conditions:
69565 //
69566 // The above copyright notice and this permission notice shall be
69567 // included in all copies or substantial portions of the Software.
69568 //
69569 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
69570 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69571 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69572 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
69573 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
69574 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
69575 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69576 // SOFTWARE.
69577
69578 // source:  https://bitbucket.org/lshift/synchrotron/src
69579 function longest_common_subsequence(file1, file2) {
69580     /* Text diff algorithm following Hunt and McIlroy 1976.
69581      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
69582      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
69583      * http://www.cs.dartmouth.edu/~doug/
69584      *
69585      * Expects two arrays of strings.
69586      */
69587     var equivalenceClasses;
69588     var file2indices;
69589     var newCandidate;
69590     var candidates;
69591     var line;
69592     var c, i, j, jX, r, s;
69593
69594     equivalenceClasses = {};
69595     for (j = 0; j < file2.length; j++) {
69596         line = file2[j];
69597         if (equivalenceClasses[line]) {
69598             equivalenceClasses[line].push(j);
69599         } else {
69600             equivalenceClasses[line] = [j];
69601         }
69602     }
69603
69604     candidates = [{file1index: -1,
69605                    file2index: -1,
69606                    chain: null}];
69607
69608     for (i = 0; i < file1.length; i++) {
69609         line = file1[i];
69610         file2indices = equivalenceClasses[line] || [];
69611
69612         r = 0;
69613         c = candidates[0];
69614
69615         for (jX = 0; jX < file2indices.length; jX++) {
69616             j = file2indices[jX];
69617
69618             for (s = 0; s < candidates.length; s++) {
69619                 if ((candidates[s].file2index < j) &&
69620                     ((s === candidates.length - 1) ||
69621                      (candidates[s + 1].file2index > j)))
69622                     break;
69623             }
69624
69625             if (s < candidates.length) {
69626                 newCandidate = {file1index: i,
69627                                 file2index: j,
69628                                 chain: candidates[s]};
69629                 if (r === candidates.length) {
69630                     candidates.push(c);
69631                 } else {
69632                     candidates[r] = c;
69633                 }
69634                 r = s + 1;
69635                 c = newCandidate;
69636                 if (r === candidates.length) {
69637                     break; // no point in examining further (j)s
69638                 }
69639             }
69640         }
69641
69642         candidates[r] = c;
69643     }
69644
69645     // At this point, we know the LCS: it's in the reverse of the
69646     // linked-list through .chain of
69647     // candidates[candidates.length - 1].
69648
69649     return candidates[candidates.length - 1];
69650 }
69651
69652
69653
69654
69655
69656
69657
69658
69659
69660
69661
69662 function diff_indices(file1, file2) {
69663     // We apply the LCS to give a simple representation of the
69664     // offsets and lengths of mismatched chunks in the input
69665     // files. This is used by diff3_merge_indices below.
69666
69667     var result = [];
69668     var tail1 = file1.length;
69669     var tail2 = file2.length;
69670
69671     for (var candidate = longest_common_subsequence(file1, file2);
69672          candidate !== null;
69673          candidate = candidate.chain)
69674     {
69675         var mismatchLength1 = tail1 - candidate.file1index - 1;
69676         var mismatchLength2 = tail2 - candidate.file2index - 1;
69677         tail1 = candidate.file1index;
69678         tail2 = candidate.file2index;
69679
69680         if (mismatchLength1 || mismatchLength2) {
69681             result.push({file1: [tail1 + 1, mismatchLength1],
69682                          file2: [tail2 + 1, mismatchLength2]});
69683         }
69684     }
69685
69686     result.reverse();
69687     return result;
69688 }
69689
69690 function diff3_merge_indices (a, o, b) {
69691     // Given three files, A, O, and B, where both A and B are
69692     // independently derived from O, returns a fairly complicated
69693     // internal representation of merge decisions it's taken. The
69694     // interested reader may wish to consult
69695     //
69696     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
69697     // Formal Investigation of Diff3." In Arvind and Prasad,
69698     // editors, Foundations of Software Technology and Theoretical
69699     // Computer Science (FSTTCS), December 2007.
69700     //
69701     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
69702     var i;
69703
69704     var m1 = diff_indices(o, a);
69705     var m2 = diff_indices(o, b);
69706
69707     var hunks = [];
69708     function addHunk(h, side) {
69709         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
69710     }
69711     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
69712     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
69713     hunks.sort();
69714
69715     var result = [];
69716     var commonOffset = 0;
69717     function copyCommon(targetOffset) {
69718         if (targetOffset > commonOffset) {
69719             result.push([1, commonOffset, targetOffset - commonOffset]);
69720             commonOffset = targetOffset;
69721         }
69722     }
69723
69724     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
69725         var firstHunkIndex = hunkIndex;
69726         var hunk = hunks[hunkIndex];
69727         var regionLhs = hunk[0];
69728         var regionRhs = regionLhs + hunk[2];
69729         while (hunkIndex < hunks.length - 1) {
69730             var maybeOverlapping = hunks[hunkIndex + 1];
69731             var maybeLhs = maybeOverlapping[0];
69732             if (maybeLhs > regionRhs) break;
69733             regionRhs = maybeLhs + maybeOverlapping[2];
69734             hunkIndex++;
69735         }
69736
69737         copyCommon(regionLhs);
69738         if (firstHunkIndex === hunkIndex) {
69739     // The "overlap" was only one hunk long, meaning that
69740     // there's no conflict here. Either a and o were the
69741     // same, or b and o were the same.
69742             if (hunk[4] > 0) {
69743                 result.push([hunk[1], hunk[3], hunk[4]]);
69744             }
69745         } else {
69746     // A proper conflict. Determine the extents of the
69747     // regions involved from a, o and b. Effectively merge
69748     // all the hunks on the left into one giant hunk, and
69749     // do the same for the right; then, correct for skew
69750     // in the regions of o that each side changed, and
69751     // report appropriate spans for the three sides.
69752     var regions = {
69753         0: [a.length, -1, o.length, -1],
69754         2: [b.length, -1, o.length, -1]
69755     };
69756             for (i = firstHunkIndex; i <= hunkIndex; i++) {
69757         hunk = hunks[i];
69758                 var side = hunk[1];
69759         var r = regions[side];
69760         var oLhs = hunk[0];
69761         var oRhs = oLhs + hunk[2];
69762                 var abLhs = hunk[3];
69763                 var abRhs = abLhs + hunk[4];
69764         r[0] = Math.min(abLhs, r[0]);
69765         r[1] = Math.max(abRhs, r[1]);
69766         r[2] = Math.min(oLhs, r[2]);
69767         r[3] = Math.max(oRhs, r[3]);
69768             }
69769     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
69770     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
69771     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
69772     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
69773             result.push([-1,
69774              aLhs,      aRhs      - aLhs,
69775              regionLhs, regionRhs - regionLhs,
69776              bLhs,      bRhs      - bLhs]);
69777         }
69778         commonOffset = regionRhs;
69779     }
69780
69781     copyCommon(o.length);
69782     return result;
69783 }
69784
69785 function diff3_merge (a, o, b, excludeFalseConflicts) {
69786     // Applies the output of Diff3.diff3_merge_indices to actually
69787     // construct the merged file; the returned result alternates
69788     // between "ok" and "conflict" blocks.
69789
69790     var result = [];
69791     var files = [a, o, b];
69792     var indices = diff3_merge_indices(a, o, b);
69793
69794     var okLines = [];
69795     function flushOk() {
69796         if (okLines.length) {
69797             result.push({ok: okLines});
69798         }
69799         okLines = [];
69800     }
69801     function pushOk(xs) {
69802         for (var j = 0; j < xs.length; j++) {
69803             okLines.push(xs[j]);
69804         }
69805     }
69806
69807     function isTrueConflict(rec) {
69808         if (rec[2] !== rec[6]) return true;
69809         var aoff = rec[1];
69810         var boff = rec[5];
69811         for (var j = 0; j < rec[2]; j++) {
69812             if (a[j + aoff] !== b[j + boff]) return true;
69813         }
69814         return false;
69815     }
69816
69817     for (var i = 0; i < indices.length; i++) {
69818         var x = indices[i];
69819         var side = x[0];
69820         if (side === -1) {
69821             if (excludeFalseConflicts && !isTrueConflict(x)) {
69822                 pushOk(files[0].slice(x[1], x[1] + x[2]));
69823             } else {
69824                 flushOk();
69825                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
69826                                         aIndex: x[1],
69827                                         o: o.slice(x[3], x[3] + x[4]),
69828                                         oIndex: x[3],
69829                                         b: b.slice(x[5], x[5] + x[6]),
69830                                         bIndex: x[5]}});
69831             }
69832         } else {
69833             pushOk(files[side].slice(x[1], x[1] + x[2]));
69834         }
69835     }
69836
69837     flushOk();
69838     return result;
69839 }
69840
69841 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
69842     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
69843         conflicts = [];
69844
69845
69846     function user(d) {
69847         return lodash.isFunction(formatUser) ? formatUser(d) : d;
69848     }
69849
69850
69851     function mergeLocation(remote, target) {
69852         function pointEqual(a, b) {
69853             var epsilon = 1e-6;
69854             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
69855         }
69856
69857         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
69858             return target;
69859         }
69860         if (option === 'force_remote') {
69861             return target.update({loc: remote.loc});
69862         }
69863
69864         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
69865         return target;
69866     }
69867
69868
69869     function mergeNodes(base, remote, target) {
69870         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
69871             return target;
69872         }
69873         if (option === 'force_remote') {
69874             return target.update({nodes: remote.nodes});
69875         }
69876
69877         var ccount = conflicts.length,
69878             o = base.nodes || [],
69879             a = target.nodes || [],
69880             b = remote.nodes || [],
69881             nodes = [],
69882             hunks = diff3_merge(a, o, b, true);
69883
69884         for (var i = 0; i < hunks.length; i++) {
69885             var hunk = hunks[i];
69886             if (hunk.ok) {
69887                 nodes.push.apply(nodes, hunk.ok);
69888             } else {
69889                 // for all conflicts, we can assume c.a !== c.b
69890                 // because `diff3_merge` called with `true` option to exclude false conflicts..
69891                 var c = hunk.conflict;
69892                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
69893                     nodes.push.apply(nodes, c.b);
69894                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
69895                     nodes.push.apply(nodes, c.a);
69896                 } else {       // changed both locally and remotely
69897                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
69898                     break;
69899                 }
69900             }
69901         }
69902
69903         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
69904     }
69905
69906
69907     function mergeChildren(targetWay, children, updates, graph) {
69908         function isUsed(node, targetWay) {
69909             var parentWays = lodash.map(graph.parentWays(node), 'id');
69910             return node.hasInterestingTags() ||
69911                 lodash.without(parentWays, targetWay.id).length > 0 ||
69912                 graph.parentRelations(node).length > 0;
69913         }
69914
69915         var ccount = conflicts.length;
69916
69917         for (var i = 0; i < children.length; i++) {
69918             var id = children[i],
69919                 node = graph.hasEntity(id);
69920
69921             // remove unused childNodes..
69922             if (targetWay.nodes.indexOf(id) === -1) {
69923                 if (node && !isUsed(node, targetWay)) {
69924                     updates.removeIds.push(id);
69925                 }
69926                 continue;
69927             }
69928
69929             // restore used childNodes..
69930             var local = localGraph.hasEntity(id),
69931                 remote = remoteGraph.hasEntity(id),
69932                 target;
69933
69934             if (option === 'force_remote' && remote && remote.visible) {
69935                 updates.replacements.push(remote);
69936
69937             } else if (option === 'force_local' && local) {
69938                 target = osmEntity$$1(local);
69939                 if (remote) {
69940                     target = target.update({ version: remote.version });
69941                 }
69942                 updates.replacements.push(target);
69943
69944             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
69945                 target = osmEntity$$1(local, { version: remote.version });
69946                 if (remote.visible) {
69947                     target = mergeLocation(remote, target);
69948                 } else {
69949                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
69950                 }
69951
69952                 if (conflicts.length !== ccount) break;
69953                 updates.replacements.push(target);
69954             }
69955         }
69956
69957         return targetWay;
69958     }
69959
69960
69961     function updateChildren(updates, graph) {
69962         for (var i = 0; i < updates.replacements.length; i++) {
69963             graph = graph.replace(updates.replacements[i]);
69964         }
69965         if (updates.removeIds.length) {
69966             graph = actionDeleteMultiple(updates.removeIds)(graph);
69967         }
69968         return graph;
69969     }
69970
69971
69972     function mergeMembers(remote, target) {
69973         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
69974             return target;
69975         }
69976         if (option === 'force_remote') {
69977             return target.update({members: remote.members});
69978         }
69979
69980         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
69981         return target;
69982     }
69983
69984
69985     function mergeTags(base, remote, target) {
69986         function ignoreKey(k) {
69987             return lodash.includes(dataDiscarded, k);
69988         }
69989
69990         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
69991             return target;
69992         }
69993         if (option === 'force_remote') {
69994             return target.update({tags: remote.tags});
69995         }
69996
69997         var ccount = conflicts.length,
69998             o = base.tags || {},
69999             a = target.tags || {},
70000             b = remote.tags || {},
70001             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
70002             tags = lodash.clone(a),
70003             changed = false;
70004
70005         for (var i = 0; i < keys.length; i++) {
70006             var k = keys[i];
70007
70008             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
70009                 if (o[k] !== a[k]) {      // changed locally..
70010                     conflicts.push(t('merge_remote_changes.conflict.tags',
70011                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
70012
70013                 } else {                  // unchanged locally, accept remote change..
70014                     if (b.hasOwnProperty(k)) {
70015                         tags[k] = b[k];
70016                     } else {
70017                         delete tags[k];
70018                     }
70019                     changed = true;
70020                 }
70021             }
70022         }
70023
70024         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
70025     }
70026
70027
70028     //  `graph.base()` is the common ancestor of the two graphs.
70029     //  `localGraph` contains user's edits up to saving
70030     //  `remoteGraph` contains remote edits to modified nodes
70031     //  `graph` must be a descendent of `localGraph` and may include
70032     //      some conflict resolution actions performed on it.
70033     //
70034     //                  --- ... --- `localGraph` -- ... -- `graph`
70035     //                 /
70036     //  `graph.base()` --- ... --- `remoteGraph`
70037     //
70038     var action = function(graph) {
70039         var updates = { replacements: [], removeIds: [] },
70040             base = graph.base().entities[id],
70041             local = localGraph.entity(id),
70042             remote = remoteGraph.entity(id),
70043             target = osmEntity$$1(local, { version: remote.version });
70044
70045         // delete/undelete
70046         if (!remote.visible) {
70047             if (option === 'force_remote') {
70048                 return actionDeleteMultiple([id])(graph);
70049
70050             } else if (option === 'force_local') {
70051                 if (target.type === 'way') {
70052                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
70053                     graph = updateChildren(updates, graph);
70054                 }
70055                 return graph.replace(target);
70056
70057             } else {
70058                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
70059                 return graph;  // do nothing
70060             }
70061         }
70062
70063         // merge
70064         if (target.type === 'node') {
70065             target = mergeLocation(remote, target);
70066
70067         } else if (target.type === 'way') {
70068             // pull in any child nodes that may not be present locally..
70069             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
70070             target = mergeNodes(base, remote, target);
70071             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
70072
70073         } else if (target.type === 'relation') {
70074             target = mergeMembers(remote, target);
70075         }
70076
70077         target = mergeTags(base, remote, target);
70078
70079         if (!conflicts.length) {
70080             graph = updateChildren(updates, graph).replace(target);
70081         }
70082
70083         return graph;
70084     };
70085
70086
70087     action.withOption = function(opt) {
70088         option = opt;
70089         return action;
70090     };
70091
70092
70093     action.conflicts = function() {
70094         return conflicts;
70095     };
70096
70097
70098     return action;
70099 }
70100
70101 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70102 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70103 function actionMove(moveIds, tryDelta, projection, cache) {
70104     var delta = tryDelta;
70105
70106     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
70107     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
70108
70109     function setupCache(graph) {
70110         function canMove(nodeId) {
70111             // Allow movement of any node that is in the selectedIDs list..
70112             if (moveIds.indexOf(nodeId) !== -1) return true;
70113
70114             // Allow movement of a vertex where 2 ways meet..
70115             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
70116             if (parents.length < 3) return true;
70117
70118             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
70119             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
70120             if (!parentsMoving) delete cache.moving[nodeId];
70121
70122             return parentsMoving;
70123         }
70124
70125         function cacheEntities(ids) {
70126             ids.forEach(function(id) {
70127                 if (cache.moving[id]) return;
70128                 cache.moving[id] = true;
70129
70130                 var entity = graph.hasEntity(id);
70131                 if (!entity) return;
70132
70133                 if (entity.type === 'node') {
70134                     cache.nodes.push(id);
70135                     cache.startLoc[id] = entity.loc;
70136                 } else if (entity.type === 'way') {
70137                     cache.ways.push(id);
70138                     cacheEntities(entity.nodes);
70139                 } else {
70140                     cacheEntities(entity.members.map(function(member) {
70141                         return member.id;
70142                     }));
70143                 }
70144             });
70145         }
70146
70147         function cacheIntersections(ids) {
70148             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
70149
70150             ids.forEach(function(id) {
70151                 // consider only intersections with 1 moved and 1 unmoved way.
70152                 var childNodes = graph.childNodes(graph.entity(id));
70153                 childNodes.forEach(function(node) {
70154                     var parents = graph.parentWays(node);
70155                     if (parents.length !== 2) return;
70156
70157                     var moved = graph.entity(id),
70158                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
70159                     if (!unmoved) return;
70160
70161                     // exclude ways that are overly connected..
70162                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
70163
70164                     if (moved.isArea() || unmoved.isArea()) return;
70165
70166                     cache.intersection[node.id] = {
70167                         nodeId: node.id,
70168                         movedId: moved.id,
70169                         unmovedId: unmoved.id,
70170                         movedIsEP: isEndpoint(moved, node.id),
70171                         unmovedIsEP: isEndpoint(unmoved, node.id)
70172                     };
70173                 });
70174             });
70175         }
70176
70177
70178         if (!cache) {
70179             cache = {};
70180         }
70181         if (!cache.ok) {
70182             cache.moving = {};
70183             cache.intersection = {};
70184             cache.replacedVertex = {};
70185             cache.startLoc = {};
70186             cache.nodes = [];
70187             cache.ways = [];
70188
70189             cacheEntities(moveIds);
70190             cacheIntersections(cache.ways);
70191             cache.nodes = lodash.filter(cache.nodes, canMove);
70192
70193             cache.ok = true;
70194         }
70195     }
70196
70197
70198     // Place a vertex where the moved vertex used to be, to preserve way shape..
70199     function replaceMovedVertex(nodeId, wayId, graph, delta) {
70200         var way = graph.entity(wayId),
70201             moved = graph.entity(nodeId),
70202             movedIndex = way.nodes.indexOf(nodeId),
70203             len, prevIndex, nextIndex;
70204
70205         if (way.isClosed()) {
70206             len = way.nodes.length - 1;
70207             prevIndex = (movedIndex + len - 1) % len;
70208             nextIndex = (movedIndex + len + 1) % len;
70209         } else {
70210             len = way.nodes.length;
70211             prevIndex = movedIndex - 1;
70212             nextIndex = movedIndex + 1;
70213         }
70214
70215         var prev = graph.hasEntity(way.nodes[prevIndex]),
70216             next = graph.hasEntity(way.nodes[nextIndex]);
70217
70218         // Don't add orig vertex at endpoint..
70219         if (!prev || !next) return graph;
70220
70221         var key = wayId + '_' + nodeId,
70222             orig = cache.replacedVertex[key];
70223         if (!orig) {
70224             orig = osmNode();
70225             cache.replacedVertex[key] = orig;
70226             cache.startLoc[orig.id] = cache.startLoc[nodeId];
70227         }
70228
70229         var start, end;
70230         if (delta) {
70231             start = projection(cache.startLoc[nodeId]);
70232             end = projection.invert(vecAdd(start, delta));
70233         } else {
70234             end = cache.startLoc[nodeId];
70235         }
70236         orig = orig.move(end);
70237
70238         var angle = Math.abs(geoAngle(orig, prev, projection) -
70239                 geoAngle(orig, next, projection)) * 180 / Math.PI;
70240
70241         // Don't add orig vertex if it would just make a straight line..
70242         if (angle > 175 && angle < 185) return graph;
70243
70244         // Don't add orig vertex if another point is already nearby (within 10m)
70245         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
70246             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
70247
70248         // moving forward or backward along way?
70249         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
70250             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
70251             d1 = geoPathLength(p1),
70252             d2 = geoPathLength(p2),
70253             insertAt = (d1 < d2) ? movedIndex : nextIndex;
70254
70255         // moving around closed loop?
70256         if (way.isClosed() && insertAt === 0) insertAt = len;
70257
70258         way = way.addNode(orig.id, insertAt);
70259         return graph.replace(orig).replace(way);
70260     }
70261
70262
70263     // Reorder nodes around intersections that have moved..
70264     function unZorroIntersection(intersection, graph) {
70265         var vertex = graph.entity(intersection.nodeId),
70266             way1 = graph.entity(intersection.movedId),
70267             way2 = graph.entity(intersection.unmovedId),
70268             isEP1 = intersection.movedIsEP,
70269             isEP2 = intersection.unmovedIsEP;
70270
70271         // don't move the vertex if it is the endpoint of both ways.
70272         if (isEP1 && isEP2) return graph;
70273
70274         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
70275             nodes2 = lodash.without(graph.childNodes(way2), vertex);
70276
70277         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
70278         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
70279
70280         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
70281             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
70282             loc;
70283
70284         // snap vertex to nearest edge (or some point between them)..
70285         if (!isEP1 && !isEP2) {
70286             var epsilon = 1e-4, maxIter = 10;
70287             for (var i = 0; i < maxIter; i++) {
70288                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
70289                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
70290                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
70291                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
70292             }
70293         } else if (!isEP1) {
70294             loc = edge1.loc;
70295         } else {
70296             loc = edge2.loc;
70297         }
70298
70299         graph = graph.replace(vertex.move(loc));
70300
70301         // if zorro happened, reorder nodes..
70302         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
70303             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
70304             graph = graph.replace(way1);
70305         }
70306         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
70307             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
70308             graph = graph.replace(way2);
70309         }
70310
70311         return graph;
70312     }
70313
70314
70315     function cleanupIntersections(graph) {
70316         lodash.each(cache.intersection, function(obj) {
70317             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
70318             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
70319             graph = unZorroIntersection(obj, graph);
70320         });
70321
70322         return graph;
70323     }
70324
70325
70326     // check if moving way endpoint can cross an unmoved way, if so limit delta..
70327     function limitDelta(graph) {
70328         lodash.each(cache.intersection, function(obj) {
70329             // Don't limit movement if this is vertex joins 2 endpoints..
70330             if (obj.movedIsEP && obj.unmovedIsEP) return;
70331             // Don't limit movement if this vertex is not an endpoint anyway..
70332             if (!obj.movedIsEP) return;
70333
70334             var node = graph.entity(obj.nodeId),
70335                 start = projection(node.loc),
70336                 end = vecAdd(start, delta),
70337                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
70338                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
70339                     function(loc) { return vecAdd(projection(loc), delta); }),
70340                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
70341                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
70342                 hits = geoPathIntersections(movedPath, unmovedPath);
70343
70344             for (var i = 0; i < hits.length; i++) {
70345                 if (lodash.isEqual(hits[i], end)) continue;
70346                 var edge = geoChooseEdge(unmovedNodes, end, projection);
70347                 delta = vecSub(projection(edge.loc), start);
70348             }
70349         });
70350     }
70351
70352
70353     var action = function(graph) {
70354         if (delta[0] === 0 && delta[1] === 0) return graph;
70355
70356         setupCache(graph);
70357
70358         if (!lodash.isEmpty(cache.intersection)) {
70359             limitDelta(graph);
70360         }
70361
70362         lodash.each(cache.nodes, function(id) {
70363             var node = graph.entity(id),
70364                 start = projection(node.loc),
70365                 end = vecAdd(start, delta);
70366             graph = graph.replace(node.move(projection.invert(end)));
70367         });
70368
70369         if (!lodash.isEmpty(cache.intersection)) {
70370             graph = cleanupIntersections(graph);
70371         }
70372
70373         return graph;
70374     };
70375
70376
70377     action.delta = function() {
70378         return delta;
70379     };
70380
70381
70382     return action;
70383 }
70384
70385 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
70386 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
70387 function actionMoveNode(nodeId, loc) {
70388     return function(graph) {
70389         return graph.replace(graph.entity(nodeId).move(loc));
70390     };
70391 }
70392
70393 function actionNoop() {
70394     return function(graph) {
70395         return graph;
70396     };
70397 }
70398
70399 /*
70400  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
70401  */
70402 function actionOrthogonalize(wayId, projection) {
70403     var threshold = 12, // degrees within right or straight to alter
70404         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
70405         upperThreshold = Math.cos(threshold * Math.PI / 180);
70406
70407
70408     var action = function(graph, t) {
70409         if (t === null || !isFinite(t)) t = 1;
70410         t = Math.min(Math.max(+t, 0), 1);
70411
70412         var way = graph.entity(wayId),
70413             nodes = graph.childNodes(way),
70414             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
70415             corner = {i: 0, dotp: 1},
70416             epsilon = 1e-4,
70417             node, loc, score, motions, i, j;
70418
70419         if (points.length === 3) {   // move only one vertex for right triangle
70420             for (i = 0; i < 1000; i++) {
70421                 motions = points.map(calcMotion);
70422                 points[corner.i] = addPoints(points[corner.i], motions[corner.i]);
70423                 score = corner.dotp;
70424                 if (score < epsilon) {
70425                     break;
70426                 }
70427             }
70428
70429             node = graph.entity(nodes[corner.i].id);
70430             loc = projection.invert(points[corner.i]);
70431             graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70432
70433         } else {
70434             var best,
70435                 originalPoints = lodash.clone(points);
70436             score = Infinity;
70437
70438             for (i = 0; i < 1000; i++) {
70439                 motions = points.map(calcMotion);
70440                 for (j = 0; j < motions.length; j++) {
70441                     points[j] = addPoints(points[j],motions[j]);
70442                 }
70443                 var newScore = squareness(points);
70444                 if (newScore < score) {
70445                     best = lodash.clone(points);
70446                     score = newScore;
70447                 }
70448                 if (score < epsilon) {
70449                     break;
70450                 }
70451             }
70452
70453             points = best;
70454
70455             for (i = 0; i < points.length; i++) {
70456                 // only move the points that actually moved
70457                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
70458                     loc = projection.invert(points[i]);
70459                     node = graph.entity(nodes[i].id);
70460                     graph = graph.replace(node.move(geoInterp(node.loc, loc, t)));
70461                 }
70462             }
70463
70464             // remove empty nodes on straight sections
70465             for (i = 0; t === 1 && i < points.length; i++) {
70466                 node = graph.entity(nodes[i].id);
70467
70468                 if (graph.parentWays(node).length > 1 ||
70469                     graph.parentRelations(node).length ||
70470                     node.hasInterestingTags()) {
70471                     continue;
70472                 }
70473
70474                 var dotp = normalizedDotProduct(i, points);
70475                 if (dotp < -1 + epsilon) {
70476                     graph = actionDeleteNode(node.id)(graph);
70477                 }
70478             }
70479         }
70480
70481         return graph;
70482
70483
70484         function calcMotion(b, i, array) {
70485             var a = array[(i - 1 + array.length) % array.length],
70486                 c = array[(i + 1) % array.length],
70487                 p = subtractPoints(a, b),
70488                 q = subtractPoints(c, b),
70489                 scale, dotp;
70490
70491             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
70492             p = normalizePoint(p, 1.0);
70493             q = normalizePoint(q, 1.0);
70494
70495             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
70496
70497             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
70498             if (array.length > 3) {
70499                 if (dotp < -0.707106781186547) {
70500                     dotp += 1.0;
70501                 }
70502             } else if (dotp && Math.abs(dotp) < corner.dotp) {
70503                 corner.i = i;
70504                 corner.dotp = Math.abs(dotp);
70505             }
70506
70507             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
70508         }
70509     };
70510
70511
70512     function squareness(points) {
70513         return points.reduce(function(sum, val, i, array) {
70514             var dotp = normalizedDotProduct(i, array);
70515
70516             dotp = filterDotProduct(dotp);
70517             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
70518         }, 0);
70519     }
70520
70521
70522     function normalizedDotProduct(i, points) {
70523         var a = points[(i - 1 + points.length) % points.length],
70524             b = points[i],
70525             c = points[(i + 1) % points.length],
70526             p = subtractPoints(a, b),
70527             q = subtractPoints(c, b);
70528
70529         p = normalizePoint(p, 1.0);
70530         q = normalizePoint(q, 1.0);
70531
70532         return p[0] * q[0] + p[1] * q[1];
70533     }
70534
70535
70536     function subtractPoints(a, b) {
70537         return [a[0] - b[0], a[1] - b[1]];
70538     }
70539
70540
70541     function addPoints(a, b) {
70542         return [a[0] + b[0], a[1] + b[1]];
70543     }
70544
70545
70546     function normalizePoint(point, scale) {
70547         var vector = [0, 0];
70548         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
70549         if (length !== 0) {
70550             vector[0] = point[0] / length;
70551             vector[1] = point[1] / length;
70552         }
70553
70554         vector[0] *= scale;
70555         vector[1] *= scale;
70556
70557         return vector;
70558     }
70559
70560
70561     function filterDotProduct(dotp) {
70562         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
70563             return dotp;
70564         }
70565
70566         return 0;
70567     }
70568
70569
70570     action.disabled = function(graph) {
70571         var way = graph.entity(wayId),
70572             nodes = graph.childNodes(way),
70573             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
70574
70575         if (squareness(points)) {
70576             return false;
70577         }
70578
70579         return 'not_squarish';
70580     };
70581
70582
70583     action.transitionable = true;
70584
70585
70586     return action;
70587 }
70588
70589 // Split a way at the given node.
70590 //
70591 // Optionally, split only the given ways, if multiple ways share
70592 // the given node.
70593 //
70594 // This is the inverse of `iD.actionJoin`.
70595 //
70596 // For testing convenience, accepts an ID to assign to the new way.
70597 // Normally, this will be undefined and the way will automatically
70598 // be assigned a new ID.
70599 //
70600 // Reference:
70601 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
70602 //
70603 function actionSplit(nodeId, newWayIds) {
70604     var wayIds;
70605
70606     // if the way is closed, we need to search for a partner node
70607     // to split the way at.
70608     //
70609     // The following looks for a node that is both far away from
70610     // the initial node in terms of way segment length and nearby
70611     // in terms of beeline-distance. This assures that areas get
70612     // split on the most "natural" points (independent of the number
70613     // of nodes).
70614     // For example: bone-shaped areas get split across their waist
70615     // line, circles across the diameter.
70616     function splitArea(nodes, idxA, graph) {
70617         var lengths = new Array(nodes.length),
70618             length,
70619             i,
70620             best = 0,
70621             idxB;
70622
70623         function wrap(index) {
70624             return utilWrap(index, nodes.length);
70625         }
70626
70627         function dist(nA, nB) {
70628             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
70629         }
70630
70631         // calculate lengths
70632         length = 0;
70633         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
70634             length += dist(nodes[i], nodes[wrap(i-1)]);
70635             lengths[i] = length;
70636         }
70637
70638         length = 0;
70639         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
70640             length += dist(nodes[i], nodes[wrap(i+1)]);
70641             if (length < lengths[i])
70642                 lengths[i] = length;
70643         }
70644
70645         // determine best opposite node to split
70646         for (i = 0; i < nodes.length; i++) {
70647             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
70648             if (cost > best) {
70649                 idxB = i;
70650                 best = cost;
70651             }
70652         }
70653
70654         return idxB;
70655     }
70656
70657
70658     function split(graph, wayA, newWayId) {
70659         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
70660             nodesA,
70661             nodesB,
70662             isArea = wayA.isArea(),
70663             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
70664
70665         if (wayA.isClosed()) {
70666             var nodes = wayA.nodes.slice(0, -1),
70667                 idxA = lodash.indexOf(nodes, nodeId),
70668                 idxB = splitArea(nodes, idxA, graph);
70669
70670             if (idxB < idxA) {
70671                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
70672                 nodesB = nodes.slice(idxB, idxA + 1);
70673             } else {
70674                 nodesA = nodes.slice(idxA, idxB + 1);
70675                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
70676             }
70677         } else {
70678             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
70679             nodesA = wayA.nodes.slice(0, idx + 1);
70680             nodesB = wayA.nodes.slice(idx);
70681         }
70682
70683         wayA = wayA.update({nodes: nodesA});
70684         wayB = wayB.update({nodes: nodesB});
70685
70686         graph = graph.replace(wayA);
70687         graph = graph.replace(wayB);
70688
70689         graph.parentRelations(wayA).forEach(function(relation) {
70690             if (relation.isRestriction()) {
70691                 var via = relation.memberByRole('via');
70692                 if (via && wayB.contains(via.id)) {
70693                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
70694                     graph = graph.replace(relation);
70695                 }
70696             } else {
70697                 if (relation === isOuter) {
70698                     graph = graph.replace(relation.mergeTags(wayA.tags));
70699                     graph = graph.replace(wayA.update({tags: {}}));
70700                     graph = graph.replace(wayB.update({tags: {}}));
70701                 }
70702
70703                 var member = {
70704                     id: wayB.id,
70705                     type: 'way',
70706                     role: relation.memberById(wayA.id).role
70707                 };
70708
70709                 graph = actionAddMember(relation.id, member)(graph);
70710             }
70711         });
70712
70713         if (!isOuter && isArea) {
70714             var multipolygon = osmRelation({
70715                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
70716                 members: [
70717                     {id: wayA.id, role: 'outer', type: 'way'},
70718                     {id: wayB.id, role: 'outer', type: 'way'}
70719                 ]});
70720
70721             graph = graph.replace(multipolygon);
70722             graph = graph.replace(wayA.update({tags: {}}));
70723             graph = graph.replace(wayB.update({tags: {}}));
70724         }
70725
70726         return graph;
70727     }
70728
70729
70730     var action = function(graph) {
70731         var candidates = action.ways(graph);
70732         for (var i = 0; i < candidates.length; i++) {
70733             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
70734         }
70735         return graph;
70736     };
70737
70738
70739     action.ways = function(graph) {
70740         var node = graph.entity(nodeId),
70741             parents = graph.parentWays(node),
70742             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
70743
70744         return parents.filter(function(parent) {
70745             if (wayIds && wayIds.indexOf(parent.id) === -1)
70746                 return false;
70747
70748             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
70749                 return false;
70750
70751             if (parent.isClosed()) {
70752                 return true;
70753             }
70754
70755             for (var i = 1; i < parent.nodes.length - 1; i++) {
70756                 if (parent.nodes[i] === nodeId) {
70757                     return true;
70758                 }
70759             }
70760
70761             return false;
70762         });
70763     };
70764
70765
70766     action.disabled = function(graph) {
70767         var candidates = action.ways(graph);
70768         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
70769             return 'not_eligible';
70770     };
70771
70772
70773     action.limitWays = function(_) {
70774         if (!arguments.length) return wayIds;
70775         wayIds = _;
70776         return action;
70777     };
70778
70779
70780     return action;
70781 }
70782
70783 // Create a restriction relation for `turn`, which must have the following structure:
70784 //
70785 //     {
70786 //         from: { node: <node ID>, way: <way ID> },
70787 //         via:  { node: <node ID> },
70788 //         to:   { node: <node ID>, way: <way ID> },
70789 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
70790 //     }
70791 //
70792 // This specifies a restriction of type `restriction` when traveling from
70793 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
70794 // (The action does not check that these entities form a valid intersection.)
70795 //
70796 // If `restriction` is not provided, it is automatically determined by
70797 // osmInferRestriction.
70798 //
70799 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
70800 // and `to.node` are used to determine which portion of the split ways become
70801 // members of the restriction.
70802 //
70803 // For testing convenience, accepts an ID to assign to the new relation.
70804 // Normally, this will be undefined and the relation will automatically
70805 // be assigned a new ID.
70806 //
70807 function actionRestrictTurn(turn, projection, restrictionId) {
70808
70809     return function(graph) {
70810         var from = graph.entity(turn.from.way),
70811             via  = graph.entity(turn.via.node),
70812             to   = graph.entity(turn.to.way);
70813
70814         function isClosingNode(way, nodeId) {
70815             return nodeId === way.first() && nodeId === way.last();
70816         }
70817
70818         function split(toOrFrom) {
70819             var newID = toOrFrom.newID || osmWay().id;
70820             graph = actionSplit(via.id, [newID])
70821                 .limitWays([toOrFrom.way])(graph);
70822
70823             var a = graph.entity(newID),
70824                 b = graph.entity(toOrFrom.way);
70825
70826             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
70827                 return [a, b];
70828             } else {
70829                 return [b, a];
70830             }
70831         }
70832
70833         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
70834             if (turn.from.node === turn.to.node) {
70835                 // U-turn
70836                 from = to = split(turn.from)[0];
70837             } else if (turn.from.way === turn.to.way) {
70838                 // Straight-on or circular
70839                 var s = split(turn.from);
70840                 from = s[0];
70841                 to   = s[1];
70842             } else {
70843                 // Other
70844                 from = split(turn.from)[0];
70845             }
70846         }
70847
70848         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
70849             to = split(turn.to)[0];
70850         }
70851
70852         return graph.replace(osmRelation({
70853             id: restrictionId,
70854             tags: {
70855                 type: 'restriction',
70856                 restriction: turn.restriction ||
70857                     osmInferRestriction(
70858                         graph,
70859                         turn.from,
70860                         turn.via,
70861                         turn.to,
70862                         projection)
70863             },
70864             members: [
70865                 {id: from.id, type: 'way',  role: 'from'},
70866                 {id: via.id,  type: 'node', role: 'via'},
70867                 {id: to.id,   type: 'way',  role: 'to'}
70868             ]
70869         }));
70870     };
70871 }
70872
70873 function actionRevert(id) {
70874     var action = function(graph) {
70875         var entity = graph.hasEntity(id),
70876             base = graph.base().entities[id];
70877
70878         if (entity && !base) {    // entity will be removed..
70879             if (entity.type === 'node') {
70880                 graph.parentWays(entity)
70881                     .forEach(function(parent) {
70882                         parent = parent.removeNode(id);
70883                         graph = graph.replace(parent);
70884
70885                         if (parent.isDegenerate()) {
70886                             graph = actionDeleteWay(parent.id)(graph);
70887                         }
70888                     });
70889             }
70890
70891             graph.parentRelations(entity)
70892                 .forEach(function(parent) {
70893                     parent = parent.removeMembersWithID(id);
70894                     graph = graph.replace(parent);
70895
70896                     if (parent.isDegenerate()) {
70897                         graph = actionDeleteRelation(parent.id)(graph);
70898                     }
70899                 });
70900         }
70901
70902         return graph.revert(id);
70903     };
70904
70905     return action;
70906 }
70907
70908 function actionRotate(rotateIds, pivot, angle, projection) {
70909
70910     var action = function(graph) {
70911         return graph.update(function(graph) {
70912             utilGetAllNodes(rotateIds, graph).forEach(function(node) {
70913                 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
70914                 graph = graph.replace(node.move(projection.invert(point)));
70915             });
70916         });
70917     };
70918
70919     return action;
70920 }
70921
70922 /*
70923  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
70924  */
70925 function actionStraighten(wayId, projection) {
70926
70927     function positionAlongWay(n, s, e) {
70928         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
70929                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
70930     }
70931
70932
70933     var action = function(graph, t) {
70934         if (t === null || !isFinite(t)) t = 1;
70935         t = Math.min(Math.max(+t, 0), 1);
70936
70937         var way = graph.entity(wayId),
70938             nodes = graph.childNodes(way),
70939             points = nodes.map(function(n) { return projection(n.loc); }),
70940             startPoint = points[0],
70941             endPoint = points[points.length-1],
70942             toDelete = [],
70943             i;
70944
70945         for (i = 1; i < points.length-1; i++) {
70946             var node = nodes[i],
70947                 point = points[i];
70948
70949             if (t < 1 || graph.parentWays(node).length > 1 ||
70950                 graph.parentRelations(node).length ||
70951                 node.hasInterestingTags()) {
70952
70953                 var u = positionAlongWay(point, startPoint, endPoint),
70954                     p = [
70955                         startPoint[0] + u * (endPoint[0] - startPoint[0]),
70956                         startPoint[1] + u * (endPoint[1] - startPoint[1])
70957                     ],
70958                     loc2 = projection.invert(p);
70959
70960                 graph = graph.replace(node.move(geoInterp(node.loc, loc2, t)));
70961
70962             } else {
70963                 // safe to delete
70964                 if (toDelete.indexOf(node) === -1) {
70965                     toDelete.push(node);
70966                 }
70967             }
70968         }
70969
70970         for (i = 0; i < toDelete.length; i++) {
70971             graph = actionDeleteNode(toDelete[i].id)(graph);
70972         }
70973
70974         return graph;
70975     };
70976
70977
70978     action.disabled = function(graph) {
70979         // check way isn't too bendy
70980         var way = graph.entity(wayId),
70981             nodes = graph.childNodes(way),
70982             points = nodes.map(function(n) { return projection(n.loc); }),
70983             startPoint = points[0],
70984             endPoint = points[points.length-1],
70985             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
70986             i;
70987
70988         if (threshold === 0) {
70989             return 'too_bendy';
70990         }
70991
70992         for (i = 1; i < points.length-1; i++) {
70993             var point = points[i],
70994                 u = positionAlongWay(point, startPoint, endPoint),
70995                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
70996                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
70997                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
70998
70999             // to bendy if point is off by 20% of total start/end distance in projected space
71000             if (isNaN(dist) || dist > threshold) {
71001                 return 'too_bendy';
71002             }
71003         }
71004     };
71005
71006
71007     action.transitionable = true;
71008
71009
71010     return action;
71011 }
71012
71013 // Remove the effects of `turn.restriction` on `turn`, which must have the
71014 // following structure:
71015 //
71016 //     {
71017 //         from: { node: <node ID>, way: <way ID> },
71018 //         via:  { node: <node ID> },
71019 //         to:   { node: <node ID>, way: <way ID> },
71020 //         restriction: <relation ID>
71021 //     }
71022 //
71023 // In the simple case, `restriction` is a reference to a `no_*` restriction
71024 // on the turn itself. In this case, it is simply deleted.
71025 //
71026 // The more complex case is where `restriction` references an `only_*`
71027 // restriction on a different turn in the same intersection. In that case,
71028 // that restriction is also deleted, but at the same time restrictions on
71029 // the turns other than the first two are created.
71030 //
71031 function actionUnrestrictTurn(turn) {
71032     return function(graph) {
71033         return actionDeleteRelation(turn.restriction)(graph);
71034     };
71035 }
71036
71037 /* Reflect the given area around its axis of symmetry */
71038 function actionReflect(reflectIds, projection) {
71039     var useLongAxis = true;
71040
71041
71042     // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
71043     // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
71044     function getSmallestSurroundingRectangle(graph, nodes) {
71045         var points = nodes.map(function(n) { return projection(n.loc); }),
71046             hull = d3polygonHull(points),
71047             centroid = d3polygonCentroid(hull),
71048             minArea = Infinity,
71049             ssrExtent = [],
71050             ssrAngle = 0,
71051             c1 = hull[0];
71052
71053         for (var i = 0; i < hull.length - 1; i++) {
71054             var c2 = hull[i + 1],
71055                 angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
71056                 poly = geoRotate(hull, -angle, centroid),
71057                 extent$$1 = poly.reduce(function(extent$$1, point) {
71058                         return extent$$1.extend(geoExtent$$1(point));
71059                     }, geoExtent$$1()),
71060                 area$$1 = extent$$1.area();
71061
71062             if (area$$1 < minArea) {
71063                 minArea = area$$1;
71064                 ssrExtent = extent$$1;
71065                 ssrAngle = angle;
71066             }
71067             c1 = c2;
71068         }
71069
71070         return {
71071             poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
71072             angle: ssrAngle
71073         };
71074     }
71075
71076
71077     var action = function(graph, t) {
71078         if (t === null || !isFinite(t)) t = 1;
71079         t = Math.min(Math.max(+t, 0), 1);
71080
71081         var nodes = utilGetAllNodes(reflectIds, graph),
71082             ssr = getSmallestSurroundingRectangle(graph, nodes);
71083
71084         // Choose line pq = axis of symmetry.
71085         // The shape's surrounding rectangle has 2 axes of symmetry.
71086         // Reflect across the longer axis by default.
71087         var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2 ],
71088             q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2 ],
71089             p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2 ],
71090             q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2 ],
71091             p, q;
71092
71093         var isLong = (geoEuclideanDistance(p1, q1) > geoEuclideanDistance(p2, q2));
71094         if ((useLongAxis && isLong) || (!useLongAxis && !isLong)) {
71095             p = p1;
71096             q = q1;
71097         } else {
71098             p = p2;
71099             q = q2;
71100         }
71101
71102         // reflect c across pq
71103         // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
71104         var dx = q[0] - p[0];
71105         var dy = q[1] - p[1];
71106         var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
71107         var b = 2 * dx * dy / (dx * dx + dy * dy);
71108         for (var i = 0; i < nodes.length; i++) {
71109             var node = nodes[i];
71110             var c = projection(node.loc);
71111             var c2 = [
71112                 a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0],
71113                 b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]
71114             ];
71115             var loc2 = projection.invert(c2);
71116             node = node.move(geoInterp(node.loc, loc2, t));
71117             graph = graph.replace(node);
71118         }
71119
71120         return graph;
71121     };
71122
71123
71124     action.useLongAxis = function(_) {
71125         if (!arguments.length) return useLongAxis;
71126         useLongAxis = _;
71127         return action;
71128     };
71129
71130
71131     action.transitionable = true;
71132
71133
71134     return action;
71135 }
71136
71137
71138
71139 var index$17 = Object.freeze({
71140         d3combobox: d3combobox,
71141         d3geoTile: d3geoTile,
71142         d3keybinding: d3keybinding
71143 });
71144
71145 /* export some legacy symbols: */
71146 var Connection = services.osm;
71147 var debug = false;
71148
71149
71150
71151
71152 var iD = Object.freeze({
71153         Connection: Connection,
71154         debug: debug,
71155         d3: index$2,
71156         lib: index$17,
71157         Context: coreContext,
71158         setAreaKeys: setAreaKeys,
71159         Difference: coreDifference,
71160         Graph: coreGraph$$1,
71161         History: coreHistory,
71162         Tree: coreTree,
71163         Entity: osmEntity$$1,
71164         Node: osmNode,
71165         Relation: osmRelation,
71166         Way: osmWay,
71167         BackgroundSource: rendererBackgroundSource,
71168         Background: rendererBackground,
71169         Features: rendererFeatures,
71170         Map: rendererMap,
71171         TileLayer: rendererTileLayer,
71172         Detect: utilDetect,
71173         actionAddEntity: actionAddEntity,
71174         actionAddMember: actionAddMember,
71175         actionAddMidpoint: actionAddMidpoint,
71176         actionAddVertex: actionAddVertex,
71177         actionChangeMember: actionChangeMember,
71178         actionChangePreset: actionChangePreset,
71179         actionChangeTags: actionChangeTags,
71180         actionCircularize: actionCircularize,
71181         actionConnect: actionConnect,
71182         actionCopyEntities: actionCopyEntities,
71183         actionDeleteMember: actionDeleteMember,
71184         actionDeleteMultiple: actionDeleteMultiple,
71185         actionDeleteNode: actionDeleteNode,
71186         actionDeleteRelation: actionDeleteRelation,
71187         actionDeleteWay: actionDeleteWay,
71188         actionDeprecateTags: actionDeprecateTags,
71189         actionDiscardTags: actionDiscardTags,
71190         actionDisconnect: actionDisconnect,
71191         actionJoin: actionJoin,
71192         actionMerge: actionMerge,
71193         actionMergePolygon: actionMergePolygon,
71194         actionMergeRemoteChanges: actionMergeRemoteChanges,
71195         actionMove: actionMove,
71196         actionMoveNode: actionMoveNode,
71197         actionNoop: actionNoop,
71198         actionOrthogonalize: actionOrthogonalize,
71199         actionRestrictTurn: actionRestrictTurn,
71200         actionReverse: actionReverse,
71201         actionRevert: actionRevert,
71202         actionRotate: actionRotate,
71203         actionSplit: actionSplit,
71204         actionStraighten: actionStraighten,
71205         actionUnrestrictTurn: actionUnrestrictTurn,
71206         actionReflect: actionReflect,
71207         behaviorAddWay: behaviorAddWay,
71208         behaviorBreathe: behaviorBreathe,
71209         behaviorCopy: behaviorCopy,
71210         behaviorDrag: behaviorDrag,
71211         behaviorDrawWay: behaviorDrawWay,
71212         behaviorDraw: behaviorDraw,
71213         behaviorEdit: behaviorEdit,
71214         behaviorHash: behaviorHash,
71215         behaviorHover: behaviorHover,
71216         behaviorLasso: behaviorLasso,
71217         behaviorOperation: behaviorOperation,
71218         behaviorPaste: behaviorPaste,
71219         behaviorSelect: behaviorSelect,
71220         behaviorTail: behaviorTail,
71221         coreContext: coreContext,
71222         coreDifference: coreDifference,
71223         coreGraph: coreGraph$$1,
71224         coreHistory: coreHistory,
71225         coreTree: coreTree,
71226         dataFeatureIcons: dataFeatureIcons,
71227         data: data,
71228         dataWikipedia: dataWikipedia,
71229         dataSuggestions: dataSuggestions,
71230         dataAddressFormats: dataAddressFormats,
71231         dataDeprecated: dataDeprecated,
71232         dataDiscarded: dataDiscarded,
71233         dataLocales: dataLocales,
71234         dataPhoneFormats: dataPhoneFormats,
71235         dataImperial: dataImperial,
71236         dataDriveLeft: dataDriveLeft,
71237         dataEn: en,
71238         geoAngle: geoAngle,
71239         geoChooseEdge: geoChooseEdge,
71240         geoCross: geoCross,
71241         geoEdgeEqual: geoEdgeEqual,
71242         geoEuclideanDistance: geoEuclideanDistance,
71243         geoExtent: geoExtent$$1,
71244         geoInterp: geoInterp,
71245         geoRawMercator: geoRawMercator,
71246         geoRoundCoords: geoRoundCoords,
71247         geoRotate: geoRotate,
71248         geoLatToMeters: geoLatToMeters,
71249         geoLineIntersection: geoLineIntersection,
71250         geoLonToMeters: geoLonToMeters,
71251         geoMetersToLat: geoMetersToLat,
71252         geoMetersToLon: geoMetersToLon,
71253         geoMetersToOffset: geoMetersToOffset,
71254         geoOffsetToMeters: geoOffsetToMeters,
71255         geoPathIntersections: geoPathIntersections,
71256         geoPathLength: geoPathLength,
71257         geoPointInPolygon: geoPointInPolygon,
71258         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
71259         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
71260         geoSphericalDistance: geoSphericalDistance,
71261         modeAddArea: modeAddArea$$1,
71262         modeAddLine: modeAddLine$$1,
71263         modeAddPoint: modeAddPoint$$1,
71264         modeBrowse: modeBrowse,
71265         modeDragNode: modeDragNode$$1,
71266         modeDrawArea: modeDrawArea,
71267         modeDrawLine: modeDrawLine,
71268         modeMove: modeMove$$1,
71269         modeRotate: modeRotate$$1,
71270         modeSave: modeSave$$1,
71271         modeSelect: modeSelect,
71272         operationCircularize: operationCircularize,
71273         operationContinue: operationContinue,
71274         operationDelete: operationDelete,
71275         operationDisconnect: operationDisconnect,
71276         operationMerge: operationMerge,
71277         operationMove: operationMove,
71278         operationOrthogonalize: operationOrthogonalize,
71279         operationReflectShort: operationReflectShort,
71280         operationReflectLong: operationReflectLong,
71281         operationReverse: operationReverse,
71282         operationRotate: operationRotate,
71283         operationSplit: operationSplit,
71284         operationStraighten: operationStraighten,
71285         osmEntity: osmEntity$$1,
71286         osmNode: osmNode,
71287         osmRelation: osmRelation,
71288         osmWay: osmWay,
71289         osmIntersection: osmIntersection,
71290         osmTurn: osmTurn,
71291         osmInferRestriction: osmInferRestriction,
71292         osmLanes: osmLanes,
71293         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
71294         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
71295         osmJoinWays: osmJoinWays,
71296         osmOneWayTags: osmOneWayTags,
71297         osmPavedTags: osmPavedTags,
71298         osmIsInterestingTag: osmIsInterestingTag,
71299         presetCategory: presetCategory,
71300         presetCollection: presetCollection,
71301         presetField: presetField,
71302         presetPreset: presetPreset,
71303         presetIndex: presetIndex,
71304         rendererBackgroundSource: rendererBackgroundSource,
71305         rendererBackground: rendererBackground,
71306         rendererFeatures: rendererFeatures,
71307         rendererMap: rendererMap,
71308         rendererTileLayer: rendererTileLayer,
71309         services: services,
71310         svgAreas: svgAreas$$1,
71311         svgDebug: svgDebug,
71312         svgDefs: svgDefs,
71313         svgGpx: svgGpx,
71314         svgIcon: svgIcon,
71315         svgLabels: svgLabels,
71316         svgLayers: svgLayers,
71317         svgLines: svgLines$$1,
71318         svgMapillaryImages: svgMapillaryImages,
71319         svgMapillarySigns: svgMapillarySigns,
71320         svgMidpoints: svgMidpoints$$1,
71321         svgOneWaySegments: svgOneWaySegments,
71322         svgOsm: svgOsm,
71323         svgPath: svgPath,
71324         svgPointTransform: svgPointTransform,
71325         svgPoints: svgPoints$$1,
71326         svgRelationMemberTags: svgRelationMemberTags,
71327         svgTagClasses: svgTagClasses,
71328         svgTurns: svgTurns,
71329         svgVertices: svgVertices$$1,
71330         uiFields: uiFields,
71331         uiFieldDefaultcheck: uiFieldCheck,
71332         uiFieldCheck: uiFieldCheck,
71333         uiFieldTypeCombo: uiFieldCombo,
71334         uiFieldMultiCombo: uiFieldCombo,
71335         uiFieldNetworkCombo: uiFieldCombo,
71336         uiFieldCombo: uiFieldCombo,
71337         uiFieldUrl: uiFieldText,
71338         uiFieldNumber: uiFieldText,
71339         uiFieldTel: uiFieldText,
71340         uiFieldEmail: uiFieldText,
71341         uiFieldText: uiFieldText,
71342         uiFieldAccess: uiFieldAccess,
71343         uiFieldAddress: uiFieldAddress,
71344         uiFieldCycleway: uiFieldCycleway,
71345         uiFieldLanes: uiFieldLanes,
71346         uiFieldLocalized: uiFieldLocalized,
71347         uiFieldMaxspeed: uiFieldMaxspeed,
71348         uiFieldRadio: uiFieldRadio,
71349         uiFieldRestrictions: uiFieldRestrictions,
71350         uiFieldTextarea: uiFieldTextarea,
71351         uiFieldWikipedia: uiFieldWikipedia,
71352         uiIntro: uiIntro,
71353         uiInit: uiInit,
71354         uiAccount: uiAccount,
71355         uiAttribution: uiAttribution,
71356         uiBackground: uiBackground,
71357         uiCmd: uiCmd,
71358         uiCommit: uiCommit,
71359         uiConfirm: uiConfirm,
71360         uiConflicts: uiConflicts,
71361         uiContributors: uiContributors,
71362         uiDisclosure: uiDisclosure,
71363         uiEntityEditor: uiEntityEditor,
71364         uiFeatureInfo: uiFeatureInfo,
71365         uiFeatureList: uiFeatureList,
71366         uiFlash: uiFlash,
71367         uiFullScreen: uiFullScreen,
71368         uiGeolocate: uiGeolocate,
71369         uiHelp: uiHelp,
71370         uiInfo: uiInfo,
71371         uiInspector: uiInspector,
71372         uiLasso: uiLasso,
71373         uiLoading: uiLoading,
71374         uiMapData: uiMapData,
71375         uiMapInMap: uiMapInMap,
71376         uiModal: uiModal,
71377         uiModes: uiModes,
71378         uiNotice: uiNotice,
71379         uiPreset: uiPreset,
71380         uiPresetIcon: uiPresetIcon,
71381         uiPresetList: uiPresetList,
71382         uiRadialMenu: uiRadialMenu,
71383         uiRawMemberEditor: uiRawMemberEditor,
71384         uiRawMembershipEditor: uiRawMembershipEditor,
71385         uiRawTagEditor: uiRawTagEditor,
71386         uiRestore: uiRestore,
71387         uiSave: uiSave,
71388         uiScale: uiScale,
71389         uiSelectionList: uiSelectionList,
71390         uiSidebar: uiSidebar,
71391         uiSourceSwitch: uiSourceSwitch,
71392         uiSpinner: uiSpinner,
71393         uiSplash: uiSplash,
71394         uiStatus: uiStatus,
71395         uiSuccess: uiSuccess,
71396         uiTagReference: uiTagReference,
71397         uiToggle: uiToggle,
71398         uiTooltipHtml: uiTooltipHtml,
71399         uiUndoRedo: uiUndoRedo,
71400         uiViewOnOSM: uiViewOnOSM,
71401         uiZoom: uiZoom,
71402         utilTagText: utilTagText,
71403         utilEntitySelector: utilEntitySelector,
71404         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
71405         utilGetAllNodes: utilGetAllNodes,
71406         utilDisplayName: utilDisplayName,
71407         utilDisplayNameForPath: utilDisplayNameForPath,
71408         utilDisplayType: utilDisplayType,
71409         utilStringQs: utilStringQs,
71410         utilQsString: utilQsString,
71411         utilPrefixDOMProperty: utilPrefixDOMProperty,
71412         utilPrefixCSSProperty: utilPrefixCSSProperty,
71413         utilSetTransform: utilSetTransform,
71414         utilEditDistance: utilEditDistance,
71415         utilFastMouse: utilFastMouse,
71416         utilGetPrototypeOf: utilGetPrototypeOf,
71417         utilAsyncMap: utilAsyncMap,
71418         utilWrap: utilWrap,
71419         utilFunctor: utilFunctor,
71420         utilSessionMutex: utilSessionMutex,
71421         utilSuggestNames: utilSuggestNames,
71422         utilTriggerEvent: utilTriggerEvent,
71423         utilGetSetValue: utilGetSetValue,
71424         d3combobox: d3combobox,
71425         d3geoTile: d3geoTile,
71426         d3keybinding: d3keybinding,
71427         validationDeprecatedTag: validationDeprecatedTag,
71428         validationDisconnectedHighway: validationDisconnectedHighway,
71429         validationManyDeletions: validationManyDeletions,
71430         validationMissingTag: validationMissingTag,
71431         validationTagSuggestsArea: validationTagSuggestsArea
71432 });
71433
71434 window.iD = iD;
71435
71436 }());
71437 //# sourceMappingURL=iD.js.map